home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 February: Technology Seed / Mac Tech Seed Feb '97.toast / OpenDoc 1.2b2c1 / Implementation / DocShell / ODPrcs.cpp < prev    next >
Encoding:
Text File  |  1997-02-13  |  67.8 KB  |  2,441 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        ODPrcs.cpp
  3.  
  4.     Contains:    OpenDoc Process runtime functions
  5.  
  6.     Owned by:    Nick Pilch
  7.  
  8.     Copyright:    © 1994 - 1997 by Apple Computer, Inc., all rights reserved.
  9.  
  10.     Change History (most recent first):
  11.  
  12.         <22>      1/8/97    DH        1401434: Removed comments; introduced
  13.                                     debugging code.
  14.         <21>      10/23/96    DH        1369514    • OpenDoc runs out of memory
  15.                                     updating prefs during a drag. Added code to
  16.                                     resize document when it can't be opened due
  17.                                     to out-of-memory.
  18.         <20>     10/4/96    CSL        1334277: Moved AboutBox code to
  19.                                     AboutBox.cpp
  20.         <19>    11.09.1996    NP        1386084: make another routine public
  21.         <18>     7/11/96    eeh        1363971: plug memory leaks
  22.         <17>     7/11/96    TJ        Fixed Name of function to check for MacOS 8
  23.         <16>     6/27/96    TJ        Use System define for CFMtype ,and check
  24.                                     for special OpenDoc editors type.
  25.         <15>     6/24/96    NP        10002: Launch time speedups
  26.         <14>     6/23/96    NP        10002: Launch time speedups.
  27.         <13>     6/19/96    NP        10002: Launch time speedups.
  28.         <12>     6/18/96    NP        10002: Launch time speedups. 1303832: Can't
  29.                                     make stationery when part editor is busy.
  30.         <11>     6/14/96    NP        10002: Launch time speedups
  31.         <10>    .06.1996    NP        10002: Launch time fixes, system process.
  32.          <9>    .05.1996    NP        1352438: Added const to parameter in
  33.                                     GetLaunchFailedParams.
  34.          <8>      5/1/96    JA        1213332: Force 68K struct alignment for
  35.                                     'vers' struct.
  36.          <7>    .03.1996    NP        Added comment about lack of error handling
  37.                                     in one routine.
  38.          <6>      3/4/96    TJ        Removed WASSERT.
  39.          <5>      3/1/96    JP        1314798: Made new documents run from temp
  40.                                     file
  41.          <4>      2/6/96    eeh        1318481: change 0 to smCurrentScript
  42.          <3>     1/15/96    TJ        Cleaned Up
  43.          <2>     1/15/96    JA        1269485: Made GetPrefsFileSpec nonstatic.
  44.                                     1303072: Changed criteria for which logo to
  45.                                     show in splash screen.
  46.         <52>    10/31/95    TJ        Made the Splash Screen Non-Modal.#1297413
  47.         <51>    10/26/95    TÇ        1296574 GM:Cannot set default memory
  48.                                     partition size.
  49.         <50>    10/25/95    TÇ        1281409 GM: OpenDoc needs an AboutBox.
  50.         <49>    10/12/95    eeh        1287143: check for open resource forks
  51.         <48>     9/29/95    eeh        1287262: use ShellDef.h
  52.         <47>     9/27/95    TÇ        1287770 GM:Crash when an application is
  53.                                     dragged over the launcher
  54.         <46>     9/27/95    eeh        1284464: use ClipStringToBytes
  55.         <45>      9/8/95    eeh        1268998: get prefs file name from resource
  56.         <44>      9/8/95    CG        #1282518 FB1:Shell moves "bad" aliases from
  57.                                     OD Libs fldr if found.
  58.         <43>      9/8/95    TÇ        1271995 FB1:Get error -35 or -44 opening
  59.                                     stationery off write-protected volume
  60.         <42>      9/5/95    TÇ        1281030 FB1:OpenDoc(tm) corrupts ODF Shared
  61.                                     libraries
  62.         <41>     8/29/95    jpa        Rename Toolbox calls for Univ Hdrs 2.1.
  63.                                     [1279173]
  64.         <40>     8/26/95    TÇ        1269688 FB1:  There is an unnecessary
  65.                                     variable
  66.         <39>     8/22/95    eeh        1278280: include RlShlDef.h
  67.         <38>     8/22/95    eeh        1276821:
  68.                                     kOpenDocShellSignature->kODShellSignature
  69.         <37>     8/16/95    CG        #1274825: Fixed creating stationery for
  70.                                     libs containing multiple editors.
  71.         <36>      8/3/95    TÇ        Remove dependency on obsolete SysPrDef.h
  72.         <35>     6/30/95    TÇ        1251872 BB: Can't open stationery if file
  73.                                     name becomes too long. 1264094 BB:Custom
  74.                                     document size cannot be attached to a
  75.                                     stationery.
  76.         <34>     6/25/95    TÇ        1242642 BB: Turn on ODDebug warning if
  77.                                     refcount is wrong in
  78.                                     ODRefCntObjectsomUninit.
  79.         <33>      6/2/95    TÇ        Need to copy resources into newly created
  80.                                     documents.  Completes fix to 4
  81.                                     BB:1233106,1242232, 1254312, 1242283
  82.         <32>     5/25/95    jpa        Removed CODE 7 -- CFM68K b1 doesn't
  83.                                     generate one. [1241078]
  84.         <31>     5/19/95    TÇ        1155852 BB: String constants need to be
  85.                                     moved to resource for Localization, 1235942
  86.                                     Launching the OpenDoc pref file causes a
  87.                                     1000 exception to be thrown, 1249396 (was
  88.                                     BB) OpenDoc shell should serialize
  89.                                     stationery creation.
  90.         <30>     5/10/95    CG        #1243610    BB: Shell should not rely on the
  91.                                     constant kNMAPid.
  92.         <29>      5/7/95    TÇ        1155852 BB: String constants need to be
  93.                                     moved to resource for Localization (mostly
  94.                                     done)
  95.         <28>     4/29/95    TÇ        1216130 BB: Shell should open top draft
  96.                                     upon receipt of open document Apple event
  97.         <27>     4/24/95    eeh        1216915: remove unnecessary param
  98.         <26>     4/24/95    eeh        1240662: send keyODActivateEventCause param
  99.                                     in activate event
  100.         <25>     4/15/95    TÇ        #1216915 DR/BB:Trying to open a document
  101.                                     that is already open causes an error.
  102.         <24>     4/14/95    TÇ        #1186294    DR/BB: Binding for editor also
  103.                                     affect making stationary.
  104.         <23>      4/7/95    eeh        1221297: eventID param to
  105.                                     VerifyAndLaunchDocumentStub
  106.         <22>     3/31/95    TÇ        1223465 BB: Opening and creating documents
  107.                                     under low disk space.  (Creating documents
  108.                                     under low disk space part fixed).
  109.                                     1211032 BB: Invalid Permissions error
  110.                                     opening locked document
  111.         <21>     3/28/95    TÇ        #1151710 BB: Toolbox running out of app
  112.                                     heap.  Document Size dialog implemented.
  113.                                     TestAndVerify now uses SIZE -1 resource in
  114.                                     OpenDoc Preferences if it exists.
  115.         <20>     3/24/95    CG        #1226064: ODTestmain can create stationary.
  116.         <19>     2/24/95    EL        1220392: fix access check bug in last
  117.                                     checkin.
  118.         <18>     2/23/95    EL        1220392: checking read only fails on file
  119.                                     share volumes.
  120.         <17>     2/20/95    TÇ        #1210979 BB: 5-$ Bugs need to be evaluated
  121.                                     and removed from Shell
  122.                                     #1221861 BB: Incomplete AOCE support needs
  123.                                     to be removed from OpenDoc
  124.         <16>     2/13/95    TÇ        1193359: BB: Opening stationery on other
  125.                                     volume causes bus error in Messaging code
  126.                                     1211032: BB: Invalid Permissions Error
  127.                                     opening locked document
  128.         <15>      2/2/95    CG        #1205177:  "Editors" and "OpenDoc
  129.                                     Libraries" folders are being registered
  130.                                     with cfm (PPC only).
  131.         <14>     1/12/95    jpa        Removed HandToHand workaround for bug in
  132.                                     Dagon a1 [1210936]
  133.         <13>      1/6/95    jpa        Added new docstub rsrcs to tables [1196515]
  134.         <12>     12/5/94    jpa        Added GetLaunchFailedParams. [1198075,
  135.                                     1158966]
  136.         <11>    10/24/94    jpa        Took out WASSERTM call & Use BlockMove, not
  137.                                     BlockMoveData [68k].
  138.         <10>    10/12/94    TÇ        68K: use local static version of HandToHand
  139.          <9>    10/10/94    TÇ        #1191470 Need both 68K and PPC document
  140.                                     stub application
  141.          <8>     10/7/94    TÇ        #1191470 Need both 68K and PPC document
  142.                                     stub application
  143.          <7>     9/29/94    RA        1189812: Mods for 68K build.
  144.          <6>      9/8/94    eeh        #1185443: forgot to eliminate strcat and
  145.                                     strcpy.
  146.          <5>      9/8/94    eeh        #1185443.  Lotso changes to separate
  147.                                     document with content from what gets
  148.                                     launched.
  149.          <4>     8/29/94    TÇ        #1158280 OpenDoc™ should not overwrite old
  150.                                     stationery files when creating new ones
  151.          <3>     8/25/94    TÇ        #1183223 Enabled launching of documents in
  152.                                     folders other than that of the OpenDoc
  153.                                     libraries.  Added new call:
  154.                                     VerifyAndLaunchDocument
  155.          <2>     8/22/94    TÇ        #1182448 System Process quits when no
  156.                                     OpenDoc documents are running
  157.          <1>     8/22/94    TÇ        first checked in
  158.          
  159.     To Do:
  160.         Change all uses of ODFileSpec and FSSpecPtr to PlatformFile objects
  161.     In Progress:
  162.         
  163. */
  164.  
  165. #ifndef _EXCEPT_
  166. #include <Except.h>
  167. #endif
  168.  
  169. #ifndef _ODDEBUG_
  170. #include "ODDebug.h"
  171. #endif
  172.  
  173. #ifndef _ODPRCS_
  174. #include "ODPrcs.h"
  175. #endif
  176.  
  177. #ifndef _SHELLDEF_
  178. #include "ShellDef.h"
  179. #endif
  180.  
  181. #ifndef SOM_Module_OpenDoc_StdDefs_defined
  182. #include <StdDefs.xh>
  183. #endif
  184.  
  185. #ifndef SOM_Module_OpenDoc_ODRegistry_defined
  186. #include "ODRgstry.xh"
  187. #endif
  188.  
  189. #ifndef _PLFMFILE_
  190. #include "PlfmFile.h"
  191. #endif
  192.  
  193. #ifndef __ERRORS__
  194. #include <Errors.h>
  195. #endif
  196.  
  197. #ifndef __FOLDERS__
  198. #include <Folders.h>
  199. #endif
  200.  
  201. #ifndef __OSEVENTS__
  202. #include <OSEvents.h>
  203. #endif
  204.  
  205. #ifndef __TOOLUTILS__
  206. #include <ToolUtils.h>
  207. #endif
  208.  
  209. #ifndef __ALIASES__
  210. #include <Aliases.h>
  211. #endif
  212.  
  213. #ifndef __FILES__
  214. #include <Files.h>
  215. #endif
  216.  
  217. #ifndef __RESOURCES__
  218. #include <Resources.h>
  219. #endif
  220.  
  221. #ifndef __DIALOGS__
  222. #include <Dialogs.h>
  223. #endif
  224.  
  225. #ifndef __EVENTS__
  226. #include <Events.h>
  227. #endif
  228.  
  229. #ifndef __APPLEEVENTS__
  230. #include <AppleEvents.h>
  231. #endif
  232.  
  233. #ifndef __GESTALT__
  234. #include <Gestalt.h>
  235. #endif
  236.  
  237. #ifndef __PROCESSES__
  238. #include <Processes.h>
  239. #endif
  240.  
  241. #ifndef __STRING__
  242. #include <String.h>
  243. #endif
  244.  
  245. #ifndef __TEXTUTILS__
  246. #include <TextUtils.h>
  247. #endif
  248.  
  249. #ifndef __STRINGS__
  250. #include <Strings.h>
  251. #endif
  252.  
  253. #ifndef __SCRIPT__
  254. #include <script.h>
  255. #endif
  256.  
  257. #ifndef __FINDER__
  258. #include <Finder.h>
  259. #endif
  260.  
  261. #ifndef _ODMEMORY_
  262. #include <ODMemory.h>
  263. #endif
  264.  
  265. #ifndef _REGISTER_
  266. #include <RegisterFileLibs.h>
  267. #endif
  268.  
  269. #ifndef _ODDPFNS_
  270. #include "ODXDpFns.h"
  271. #endif
  272.  
  273. #ifndef _ERRUTILS_
  274. #include "ErrUtils.h"
  275. #endif
  276.  
  277. #ifndef PREFSFILE_H
  278. #include "PrefsFile.h"
  279. #endif
  280.  
  281. #ifndef _PREFSDEF_
  282. #include "PrefsDef.h"
  283. #endif
  284.  
  285. //==============================================================================
  286. // Constants
  287. //==============================================================================
  288.  
  289. #define kMaxFileNameLen        31
  290.  
  291. #define kNumDocStubRsrcs    11    /* was 12 before CFM68K a3 */
  292.  
  293. const ODULong docStubRsrcType[kNumDocStubRsrcs] = 
  294.     { 
  295.         kDocStubRsrcType,
  296.         kDocStubRsrcType,
  297.         kDocStubRsrcType,
  298.         kDocStubRsrcType,
  299.         kDocStubRsrcType,
  300.         kDocStubRsrcType,
  301.         kDocStubRsrcType,
  302.         kDocStubRsrcType,
  303. //        kDocStubRsrcType,
  304.         kDocStubRsrcType,
  305.         kDocStubRsrcType,
  306.         kSIZERsrcType 
  307.     };
  308.  
  309. const ODULong docStubRsrcID[kNumDocStubRsrcs] = 
  310.     {
  311.         kDocStubRsrcID0,
  312.         kDocStubRsrcID1,
  313.         kDocStubRsrcID2,
  314.         kDocStubRsrcID3,
  315.         kDocStubRsrcID4,
  316.         kDocStubRsrcID5,
  317.         kDocStubRsrcID6,
  318.         kDocStubRsrcID7,
  319.         kDocStubRsrcID8,
  320.         kDocStubRsrcID9,
  321. //        kDocStubRsrcID10,
  322.         kDocStubSIZEID
  323.     };
  324.  
  325. const ODULong copiedRsrcType[kNumDocStubRsrcs] = 
  326.     {
  327.         kcfrgRsrcType,
  328.         kMainCFMType,
  329.         kscszRsrcType,
  330.         kMainCFMType,
  331.         kMainCFMType,
  332.         kCODERsrcType,
  333.         kCODERsrcType,
  334.         kCODERsrcType,
  335. //        kCODERsrcType,
  336.         kMainCFMType,
  337.         kMainCFMType,
  338.         kSIZERsrcType 
  339.     };
  340.  
  341. const ODULong copiedRsrcID[kNumDocStubRsrcs] = 
  342.     {
  343.         kcfrgID,
  344.         kMainCFMPPCID,
  345.         kscszID,
  346.         kMainCFM68KID,
  347.         kMainCFM68KID1,
  348.         kCODEID0,
  349.         kCODEID1,
  350.         kCODEID6,
  351. //        kCODEID7,
  352.         kSOMMemCFM68KID,
  353.         kSOMMemCFMPPCID,
  354.         kSIZEID
  355.     };
  356.  
  357.  
  358. enum
  359. {
  360.     kIsNotSameAsStub        = 0,
  361.     kIsSameAsStub            = 1,
  362.     kIsAlreadyLaunched        = 2
  363. };
  364. typedef ODSShort DocStubType;
  365.  
  366. struct ITextData {
  367.     ScriptCode      theScriptCode;
  368.     LangCode     theLangCode;
  369.     Str255         theText;
  370. };
  371. typedef struct ITextData ITextData;
  372.  
  373. struct EditorUserStringList {
  374.     Str255                     editor;
  375.     ITextData                name;
  376.     EditorUserStringList*     next;
  377. };
  378. typedef struct EditorUserStringList EditorUserStringList;
  379.  
  380. //==============================================================================
  381. // Macros
  382. //==============================================================================
  383.  
  384. #define CHECK(EXPR)    if ((err=(EXPR)) == noErr) ; else return err
  385. #define CHECKR(EXPR,RET)    if ((err=(EXPR)) == noErr) ; else return (RET)
  386.  
  387. #if ODDebug
  388. #define ODPrcsDebugStr(x) DebugStr(c2pstr(x))
  389. #else
  390. #define ODPrcsDebugStr(x)
  391. #endif
  392.  
  393. //==============================================================================
  394. // Function Prototype
  395. //==============================================================================
  396.  
  397. static ODBoolean    IsAProcessRunning(OSType procType, OSType procSignature);
  398.  
  399. static void    CreateTempName(short seed, Str255 name, ODBoolean isFile);
  400. static OSErr CreateUniqueTmpFolderForFile(ODFileSpec* result,
  401.         Str63 fileName);
  402. static OSErr MakeDocumentStub(AEDesc *document, FSSpec* documentStub,
  403.         FSSpec* documentSpec,
  404.         DocStubType* isDuplicate, DescType eventID, ODBoolean unsavedDoc);
  405.  
  406. // Document Launching
  407. static OSErr     TestAndUpdate(Handle origRsrc,ResType rtype,short rid);
  408. static OSErr    CreateStationerySeed(FSSpecPtr theDocument, FSSpec* seedFSSPtr);
  409. static size_t    ODXstrlen(const char *s);
  410. static char*     ODXstrncpy(char* destStr, char* srcStr, size_t n);
  411. static char*     ODXstrncat(char* destStr, char* srcStr, size_t n);
  412. static char        ODXmemcmp(char* buffer1,char* buffer2,unsigned int len);
  413. ODBoolean myEqualPascalStrings(ConstStr255Param str1, ConstStr255Param str2);
  414. ODFileSpec    FindODBinary(ODSShort fldrVRefNum, 
  415.                                         ODSLong fldrDirID, Str255 pbinaryName);
  416. OSErr GetEditorUserStringPairs(ODSShort resRefNum, EditorUserStringList** pairs, ODUShort* editorCount);
  417. OSErr GetEditorSetFromNMAP( ODHandle nmap, EditorUserStringList** pairs, ODUShort* editorCount );
  418. static void MoveToTrash( short vRefnum, long dirID, Str255 name );
  419.  
  420.  
  421. //==============================================================================
  422. // GetOpenDocBinaryFileSpec
  423. //==============================================================================
  424. #if 0
  425. ODFileSpec    GetOpenDocBinaryFileSpec(char* binaryName)
  426. {
  427.  
  428.     ODFileSpec filespec;
  429.     Str255    pbinaryName;
  430.     ODUShort pbinaryLen = 0;
  431.     
  432.     if (binaryName)
  433.     {
  434.         pbinaryLen = ODXstrlen(binaryName);
  435.         
  436.         if (pbinaryLen>255)
  437.         {
  438.             pbinaryLen = 255;
  439.         }
  440.         
  441.         ODXstrncpy((char*)&(pbinaryName[1]),binaryName,pbinaryLen);
  442.     }
  443.     
  444.     ClipStringToBytes( pbinaryName, pbinaryLen, smCurrentScript );
  445.     
  446.     ODFileSpec odLibsFldrSpec = GetOpenDocLibsFldrSpec();
  447.     ODSLong dirID = GetFldrDirID(odLibsFldrSpec);
  448.     filespec = FindODBinary(odLibsFldrSpec.vRefNum, dirID, pbinaryName);
  449.  
  450.     return filespec;
  451. }
  452.  
  453. //==============================================================================
  454. // FindODBinary
  455. //==============================================================================
  456.  
  457. ODFileSpec    FindODBinary(ODSShort fldrVRefNum, 
  458.                                          ODSLong fldrDirID, Str255 pbinaryName)
  459. {
  460.     CInfoPBRec        CinfoPB;
  461.     Str255            fileName;
  462.     ODFileSpec        fileSpec;
  463.     FSMakeFSSpec(    fldrVRefNum, 
  464.                      fldrDirID, 
  465.                      pbinaryName, &fileSpec);
  466.  
  467.         //check that this is not a bogus folder
  468.     if (fldrDirID != -1)
  469.     {
  470.         memset (&CinfoPB,0,sizeof(CinfoPB));
  471.         CinfoPB.dirInfo.ioNamePtr = (StringPtr)&fileName;
  472.         CinfoPB.dirInfo.ioFDirIndex = 1;
  473.         CinfoPB.dirInfo.ioVRefNum = fldrVRefNum;
  474.         CinfoPB.dirInfo.ioDrDirID = fldrDirID;
  475.         
  476.             // Loop through all the files in Library folder
  477.         for(ODSShort i = PBGetCatInfoSync(&CinfoPB); 
  478.                         i == noErr; 
  479.                        i = PBGetCatInfoSync(&CinfoPB))
  480.         {
  481.                 // if this is a folder
  482.             if ((CinfoPB.dirInfo.ioFlAttrib & (1<<4))) 
  483.             {
  484.                 FSSpec fldrSpec;
  485.                 FSMakeFSSpec(CinfoPB.hFileInfo.ioVRefNum, 
  486.                              CinfoPB.hFileInfo.ioFlParID, 
  487.                              fileName, &fldrSpec);
  488.                 OSErr err = RegisterFileLibs(&fldrSpec);
  489.                 fileSpec = FindODBinary(fldrVRefNum, 
  490.                                         CinfoPB.dirInfo.ioDrDirID, 
  491.                                         pbinaryName);
  492.             }
  493.             else
  494.             {
  495.                     // if this is an alias, resolve and do the right thing
  496.                 if ((CinfoPB.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) /* kIsAlias */)
  497.                 {
  498.                     FSSpec    aliasSpec;
  499.                     Boolean    targetIsFolder = kODFalse;
  500.                     Boolean    wasAliased = kODFalse;
  501.                     
  502.                     ODError result = FSMakeFSSpec(CinfoPB.hFileInfo.ioVRefNum, 
  503.                                           CinfoPB.hFileInfo.ioFlParID, 
  504.                                           fileName, &aliasSpec);
  505.                     if (result == noErr)
  506.                     {
  507.                             //resolve alias
  508.                         result = ResolveAliasFile(&aliasSpec, kODTrue, 
  509.                                               &targetIsFolder, &wasAliased);
  510.                         if (result == noErr)
  511.                         {
  512.                             if (aliasSpec.vRefNum != fldrVRefNum)
  513.                                 MoveToTrash( CinfoPB.hFileInfo.ioVRefNum, 
  514.                                              CinfoPB.hFileInfo.ioFlParID, fileName );
  515.                             else
  516.                             {
  517.                                 if (targetIsFolder)
  518.                                 {
  519.                                     OSErr err = RegisterFileLibs(&aliasSpec);
  520.                                     ODSLong dirID = GetFldrDirID(aliasSpec);
  521.                                     FindODBinary(aliasSpec.vRefNum, 
  522.                                                   dirID, pbinaryName);
  523.                                 }
  524.                                 else
  525.                                 {
  526.                                     // if this file's name == pbinaryName, make an FSSpec and return it
  527.                                     if (myEqualPascalStrings(pbinaryName, 
  528.                                                               fileName))
  529.                                         FSMakeFSSpec(aliasSpec.vRefNum, 
  530.                                                       aliasSpec.parID, fileName, 
  531.                                                       &fileSpec);                                    
  532.                                 }
  533.                             }
  534.                         }
  535.                     }
  536.                 }
  537.                 else
  538.                 {
  539.                     // if this file's name == pbinaryName, make an FSSpec and return it
  540.                     if (myEqualPascalStrings(pbinaryName, fileName))
  541.                     {
  542.                         FSMakeFSSpec(CinfoPB.hFileInfo.ioVRefNum, 
  543.                                       CinfoPB.hFileInfo.ioFlParID, 
  544.                                       fileName, &fileSpec);
  545.                     }                            
  546.                 }
  547.             }
  548.  
  549.             CinfoPB.hFileInfo.ioFDirIndex++;
  550.                 //need to do this each time since PBGetCatInfo call returns val here
  551.             CinfoPB.hFileInfo.ioNamePtr = (StringPtr)&fileName;
  552.             CinfoPB.hFileInfo.ioVRefNum = fldrVRefNum;
  553.             CinfoPB.hFileInfo.ioDirID = fldrDirID;  
  554.         }
  555.     }
  556.     return fileSpec;
  557. }
  558.  
  559. //==============================================================================
  560. // GetOpenDocLibsFldrSpec
  561. //==============================================================================
  562.  
  563. OSErr GetOpenDocLibsFldrSpec(ODFileSpec* fileSpec)
  564. {
  565.     long        odDirID, libsFldrDirID;
  566.     short        odVRef, libsFldrVRefNum;
  567.     FileSpec    odFldrSpec;
  568.     Str255        folderName;
  569.     OSErr        result;
  570.  
  571.     GetIndString(folderName, kODXLibsFldrStrID, kODXLibsFldrStrIndex);
  572.  
  573.     if (folderName[0] == 0)
  574.         ODPrcsDebugStr("\pResource Error: OpenDoc Libraries string not found!");
  575.         
  576.     OSErr result = FindFolder(kOnSystemDisk, kExtensionFolderType, 
  577.                                 kDontCreateFolder, &libsFldrVRefNum, 
  578.                                 &libsFldrDirID);
  579.     if (result == noErr)
  580.     {
  581.         CInfoPBRec        CinfoPB;
  582.  
  583.         memset (&CinfoPB, 0 ,sizeof(CinfoPB));
  584.  
  585.         CinfoPB.dirInfo.ioNamePtr = (StringPtr)&folderName;
  586.         CinfoPB.dirInfo.ioFDirIndex = 0;
  587.         CinfoPB.dirInfo.ioVRefNum = libsFldrVRefNum;
  588.         CinfoPB.dirInfo.ioDrDirID = libsFldrDirID;
  589.         
  590.         result = PBGetCatInfoSync(&CinfoPB);
  591.         if (result == noErr)
  592.         {
  593.             odVRef  = CinfoPB.dirInfo.ioVRefNum;
  594.             odDirID = CinfoPB.dirInfo.ioDrParID;
  595.             result = FSMakeFSSpec(odVRef, odDirID, folderName, &odFldrSpec);
  596.         }
  597.     }
  598.     
  599.     *fileSpec = odFldrSpec;
  600.     return result;
  601. }
  602.  
  603. //------------------------------------------------------------------------------
  604. // GetFldrDirID
  605. //------------------------------------------------------------------------------
  606.  
  607. long GetFldrDirID(ODFileSpec theFolderSpec)
  608. {
  609.     long        dirID = -1;
  610.     CInfoPBRec    theParamBlock;
  611.  
  612.     memset (&theParamBlock, 0, sizeof(theParamBlock));
  613.  
  614.     theParamBlock.dirInfo.ioFDirIndex = 0;
  615.     theParamBlock.dirInfo.ioNamePtr = theFolderSpec.name;
  616.     theParamBlock.dirInfo.ioVRefNum = theFolderSpec.vRefNum;
  617.     theParamBlock.dirInfo.ioDrDirID = theFolderSpec.parID;
  618.     ODError result = PBGetCatInfoSync(&theParamBlock);
  619.  
  620.     if (result == noErr && (theParamBlock.hFileInfo.ioFlAttrib & (1<<4))) 
  621.         dirID = theParamBlock.dirInfo.ioDrDirID;
  622.  
  623.     return dirID;
  624. }
  625.  
  626. #ifdef NEEDSYSTEMPROCESS
  627. #define    kODSysProcessType            0x4150504C    // 'APPL' ?should be 'appe' eventually
  628. #define kODSysProcessSignature        0x6F647370    // 'odsp'
  629.  
  630. //==============================================================================
  631. // IsODSysProcessRunning
  632. //==============================================================================
  633.  
  634. ODBoolean    IsODSysProcessRunning()
  635. {
  636.     return IsAProcessRunning(kODSysProcessType,kODSysProcessSignature);
  637.  
  638.     ProcessSerialNumber psn = {0,kNoProcess};
  639.     ProcessInfoRec aProcess;
  640.     aProcess.processInfoLength = sizeof(ProcessInfoRec);
  641.     aProcess.processName = NULL;
  642.     aProcess.processAppSpec = NULL;
  643.     
  644.     while (GetNextProcess(&psn) == noErr)
  645.         if (GetProcessInformation(&psn,&aProcess) == noErr)
  646.             if (aProcess.processType == kODSysProcessType &&
  647.                 aProcess.processSignature == kODSysProcessSignature)
  648.                     return true;
  649.     return false;
  650. }
  651. #endif
  652. #endif /* 0 */
  653. //==============================================================================
  654. // AreODDocumentsRunning
  655. //==============================================================================
  656.  
  657. ODBoolean    AreODDocumentsRunning()
  658. {
  659.     ProcessSerialNumber    psn = {0, kNoProcess};
  660.     ProcessInfoRec        aProcess;
  661.     ODBoolean            result = kODFalse;
  662.     PlatformFile*        processFile = new PlatformFile;
  663.     FSSpec                processAppSpec;
  664.     OSErr                thePMErr = noErr;
  665.     
  666.     aProcess.processInfoLength = sizeof(ProcessInfoRec);
  667.     aProcess.processName = NULL;
  668.     aProcess.processAppSpec = &processAppSpec;
  669.     
  670.     while (GetNextProcess(&psn) == noErr)
  671.     {
  672.         if ((thePMErr = GetProcessInformation(&psn, &aProcess)) == noErr)
  673. //            if (aProcess.processType != 'APPL' &&
  674. //                aProcess.processSignature == kODShellSignature)
  675. //                    return true;
  676.         {
  677.             processFile->Specify(aProcess.processAppSpec);
  678.             if (processFile->IsOpenDocDocument())
  679.             {
  680.                 result = kODTrue;
  681.                 break;
  682.             }
  683.         }
  684.         else
  685.             ODPrcsDebugStr("AreODDocumentsRunning: GetProcessInformation failed!");
  686.     }
  687.  
  688.     delete processFile;
  689.     return result;
  690. }
  691.  
  692. //==============================================================================
  693. // FileIsReadOnly
  694. //==============================================================================
  695.  
  696. OSErr FileIsReadOnly(ODFileSpec* fs, ODBoolean* result)
  697. {
  698. // Note: copied from PlatformFile::IsLocked.  OpenDoc™ DOES NOT link in Util.lib. -TÇ
  699.  
  700.     CInfoPBRec    pbBlock;
  701.     *result = kODFalse;
  702.     OSErr err = noErr;
  703.  
  704.     // Check to see whether the volume is locked
  705.  
  706.     // Eric's original code with slight modifications.
  707.     // Appears to be needed in the case of a locked floppy. -TÇ
  708.     HParamBlockRec pb;
  709.     pb.volumeParam.ioCompletion = kODNULL;
  710.     pb.volumeParam.ioNamePtr = kODNULL;
  711.     pb.volumeParam.ioVRefNum = fs->vRefNum;
  712.     pb.volumeParam.ioVolIndex = 0;
  713.  
  714.     err = PBHGetVInfoSync(&pb);
  715.     if (err) return err;
  716.  
  717.     *result = (pb.volumeParam.ioVAtrb & 0x80) ? kODTrue : kODFalse;
  718.     
  719.     // Check to see whether the directory is locked
  720.     if (*result == kODFalse) {
  721.         // first assume it is a file share volume
  722.         HParamBlockRec    paramBlk;
  723.         paramBlk.accessParam.ioCompletion = kODNULL;
  724.         paramBlk.accessParam.ioNamePtr = kODNULL;
  725.         paramBlk.accessParam.ioVRefNum = fs->vRefNum;
  726.         paramBlk.accessParam.ioDirID = fs->parID;
  727.         paramBlk.accessParam.ioACAccess = 0;
  728.         err = PBHGetDirAccessSync(¶mBlk);
  729.         
  730.         if (err == noErr) {        /* it is a file share volume, look at the access right */
  731.             if ((paramBlk.accessParam.ioACAccess & 0x04000000) == 0) /* no write access */
  732.                 *result = kODTrue;
  733.         }
  734.         else if (err == paramErr) { /* it is not file share, look at directory */
  735.             pbBlock.dirInfo.ioCompletion = kODNULL;
  736.             pbBlock.dirInfo.ioNamePtr = kODNULL;
  737.             pbBlock.dirInfo.ioVRefNum = fs->vRefNum;
  738.             pbBlock.dirInfo.ioFDirIndex = -1;
  739.             pbBlock.dirInfo.ioDrDirID = fs->parID;
  740.             pbBlock.dirInfo.ioFlAttrib = 0;
  741.             err = PBGetCatInfoSync(&pbBlock);
  742.             if (err) return err;
  743.             if (pbBlock.dirInfo.ioFlAttrib & 1)
  744.                 *result = kODTrue;            
  745.         }
  746.         else
  747.             return err;
  748.     }
  749.  
  750.     // Check to see whether the file is locked
  751.     if (*result == kODFalse) {    
  752.         pbBlock.hFileInfo.ioCompletion = kODNULL;
  753.         pbBlock.hFileInfo.ioFDirIndex = 0;
  754.         pbBlock.hFileInfo.ioNamePtr = fs->name;
  755.         pbBlock.hFileInfo.ioVRefNum = fs->vRefNum;
  756.         pbBlock.hFileInfo.ioDirID = fs->parID;
  757.         
  758.         err =  PBGetCatInfoSync(&pbBlock);
  759.         if (err) return err;
  760.  
  761.         if (pbBlock.hFileInfo.ioFlAttrib & 1)
  762.             *result = kODTrue;
  763.     }
  764.             
  765.     return noErr;
  766. }
  767.  
  768. //==============================================================================
  769. // GetVolumeWritableSpace
  770. //==============================================================================
  771.  
  772. ODULong    GetVolumeWritableSpace(ODFileSpec* fs, ODULong* error)
  773. {    
  774.     ODULong err = noErr;
  775.     HParamBlockRec    paramBlk;
  776.     ODBoolean        writable = kODFalse;
  777.     
  778.     if (error == kODNULL)
  779.         error = &err;
  780.         
  781.     paramBlk.accessParam.ioCompletion = kODNULL;
  782.     paramBlk.accessParam.ioNamePtr = kODNULL;
  783.     paramBlk.accessParam.ioVRefNum = fs->vRefNum;
  784.     paramBlk.accessParam.ioDirID = fs->parID;
  785.     paramBlk.accessParam.ioACAccess = 0;
  786.     *error = PBHGetDirAccessSync(¶mBlk);
  787.     
  788.     if (*error == noErr) {        /* it is a file share volume, look at the access right */
  789.         if (paramBlk.accessParam.ioACAccess & 0x04000000)
  790.             writable = kODTrue;
  791.     }
  792.     else if (*error == paramErr) { /* it is not file share, look at directory */
  793.         CInfoPBRec    pbBlock;
  794.         pbBlock.dirInfo.ioCompletion = kODNULL;
  795.         pbBlock.dirInfo.ioNamePtr = kODNULL;
  796.         pbBlock.dirInfo.ioVRefNum = fs->vRefNum;
  797.         pbBlock.dirInfo.ioFDirIndex = -1;
  798.         pbBlock.dirInfo.ioDrDirID = fs->parID;
  799.         pbBlock.dirInfo.ioFlAttrib = 0;
  800.         *error = PBGetCatInfoSync(&pbBlock);
  801.         if (*error) return 0;
  802.         
  803.         if (!(pbBlock.dirInfo.ioFlAttrib & 1))
  804.             writable = kODTrue;
  805.     }
  806.     else
  807.          return 0;
  808.  
  809.     if (writable != kODFalse) {
  810.         // how much space on this writable volume?
  811.         HParamBlockRec hpb;
  812.         hpb.volumeParam.ioVolIndex = 0;
  813.         hpb.volumeParam.ioNamePtr = kODNULL;
  814.         hpb.volumeParam.ioVRefNum = fs->vRefNum;
  815.         
  816.         *error = PBHGetVInfoSync(&hpb);
  817.         if (*error) return 0;
  818.         
  819.         if (!(hpb.volumeParam.ioVAtrb & 0x80))
  820.             return ((hpb.volumeParam.ioVFrBlk * hpb.volumeParam.ioVAlBlkSiz) / 1024);
  821.         // Appears to be needed in the case of a locked floppy. -TÇ
  822.     }    
  823.  
  824.     *error = kODErrDirectoryNotHaveWriteAccess;
  825.     return 0;
  826. }
  827.  
  828. //==============================================================================
  829. // GetDescFSSpec
  830. //==============================================================================
  831.  
  832. OSErr
  833. GetDescFSSpec(AEDesc *desc, FSSpec &spec)
  834. {
  835.     AEDesc resultDesc;
  836.     OSErr err = AECoerceDesc(desc, typeFSS, &resultDesc);
  837.     if (err) return err;
  838.     spec = **(FSSpec**)(resultDesc.dataHandle);
  839.     AEDisposeDesc(&resultDesc);
  840.     return noErr;
  841. }
  842.  
  843.  
  844. //==============================================================================
  845. // CreateTempName
  846. //==============================================================================
  847.  
  848. static void    CreateTempName(short seed, Str255 name, ODBoolean isFile)
  849. {
  850.     // Don't modify this one!
  851.     char* nmSeed = isFile? "ODShellTempFile" : "ODShellTempFolder";
  852.     ODXstrncpy((char*)name, nmSeed, ODXstrlen(nmSeed)+1);
  853.  
  854.     char theNum[10];
  855.     NumToString(seed, (StringPtr)theNum); 
  856. //    WASSERT(theNum[0] <= 5);
  857.     p2cstr((StringPtr)theNum);
  858.  
  859.     ODXstrncat((char*)name, theNum, ODXstrlen(theNum)+1);
  860.     c2pstr((char *)name);
  861. }
  862.  
  863. OSErr CreateUniqueTmpFolderForFile(ODFileSpec* result,
  864.         Str63 fileName)
  865. {
  866.     Str255        myName;
  867.     ODSLong    myDirID;
  868.     ODSShort    myVRef;
  869.  
  870.     FindFolder(kOnSystemDisk, kTemporaryFolderType, kCreateFolder, &myVRef, &myDirID);
  871.  
  872.     OSErr err;
  873.     short limit = 100;
  874.     short seed = 1;
  875.     while (--limit)
  876.     {
  877.         CreateTempName(seed++, myName, kODFalse);
  878.         long createdDirID;
  879.         err = DirCreate(myVRef, myDirID, myName,
  880.                 &createdDirID);
  881.         if (err == noErr)
  882.         {
  883.             FSMakeFSSpec(myVRef, createdDirID, fileName, result);
  884.             return noErr;
  885.         }
  886.     }
  887.     return err;
  888. }
  889.  
  890. //------------------------------------------------------------------------------
  891. // GetLaunchFailedParams
  892. //------------------------------------------------------------------------------
  893.  
  894. void GetLaunchFailedParams(const AppleEvent *ae, long &launchError,
  895.                             ProcessSerialNumber *psn, Str255 appName,
  896.                             Str255 libName)
  897. {
  898.     OSErr err;
  899.     DescType type;
  900.     Size size;
  901.     
  902.     err= AEGetParamPtr(ae, keyErrorNumber, typeLongInteger, &type,
  903.                             &launchError, sizeof(launchError), &size);
  904.     if (err)
  905.         launchError = err;
  906.         
  907.     if (psn!=NULL) {
  908.         psn->lowLongOfPSN = 0;
  909.         psn->highLongOfPSN = 0;
  910.         (void) AEGetParamPtr(ae,keyProcessSerialNumber,typeProcessSerialNumber,&type,
  911.                             psn,sizeof(*psn), &size);
  912.     }
  913.     
  914.     err= AEGetParamPtr(ae, 'APPL', typeChar, &type, &appName[1], 255, &size);
  915.     appName[0] = err ?0 :size;
  916.     
  917.     err= AEGetParamPtr(ae, 'LIBN', typeChar, &type, &libName[1], 255, &size);
  918.     libName[0] = err ?0 :size;
  919. }
  920.  
  921. //------------------------------------------------------------------------------
  922. // MakeDocumentStub
  923. //------------------------------------------------------------------------------
  924.  
  925. static OSErr MakeDocumentStub(AEDesc *document, FSSpec* documentStub,
  926.                                 FSSpec* documentSpec,
  927.                                 DocStubType* isDuplicate,
  928.                                 DescType eventID,
  929.                                 ODBoolean unsavedDoc)
  930. {
  931.     OSErr err;
  932.     
  933.     FSSpec documentFSSpec;
  934.     CHECK(GetDescFSSpec(document, documentFSSpec));
  935.     *documentSpec = documentFSSpec;
  936.  
  937.     FInfo documentFInfo;
  938.     err= FSpGetFInfo(&documentFSSpec, &documentFInfo);
  939.     if (err) return err;
  940.  
  941.      // DON'T WORRY ABOUT OPEN LIBRARIES    
  942.     if (documentFInfo.fdType != kCFragLibraryFileType &&
  943.         documentFInfo.fdType != kODSpecialEditorType)
  944.     {
  945.         // BUT DON'T RELAUNCH OPEN DOCUMENTS
  946.         if (WasLaunchedThenActivate(documentSpec, eventID, err ))
  947.         {
  948.             *isDuplicate = kIsAlreadyLaunched;
  949.             return err;
  950.         }
  951.     }
  952.  
  953.     // if it's a read-only file OR if it's on a server OR if it's stationery,
  954.     // OR it's unsaved (i.e. a New document)
  955.     // make a new one.
  956.     
  957.     ODBoolean makeNewOne;
  958.     err = FileIsReadOnly(&documentFSSpec, &makeNewOne);
  959.     if (err) return err;
  960.     makeNewOne = makeNewOne || (((documentFInfo.fdFlags)&kIsStationary)!=0) ||
  961.         (documentFInfo.fdCreator != kODShellSignature) || unsavedDoc;
  962.     if (!makeNewOne || 
  963.         documentFInfo.fdType == kCFragLibraryFileType ||
  964.         documentFInfo.fdType == kODSpecialEditorType)
  965.     {
  966.         *documentStub = documentFSSpec;
  967.         *isDuplicate = kIsSameAsStub;
  968.         return noErr;
  969.     }
  970.     
  971.     // if we get here we need a new file....
  972.     *isDuplicate = kIsNotSameAsStub;
  973.  
  974.     FSSpec newFileSpec;
  975.     ODHandle size0 = kODNULL;
  976.     ODHandle size1 = kODNULL;
  977.  
  978.     err = CreateUniqueTmpFolderForFile(&newFileSpec, documentFSSpec.name);    
  979.     if (err) return err;
  980.  
  981.     err = FSpCreate( &newFileSpec, kODShellSignature, documentFInfo.fdType,
  982.             smSystemScript );
  983.     FSpCreateResFile( &newFileSpec, kODShellSignature, documentFInfo.fdType,
  984.             smSystemScript );
  985.     if (!err)
  986.         *documentStub = newFileSpec;
  987.  
  988.     // Need to copy over custom SIZE 0 & 1 resource for proper custom heapsize behaviour
  989.     // for readonly documents and documents newly created from stationery.
  990.     
  991.     short theCurResFile = CurResFile();
  992.     short docResFile = FSpOpenResFile((const FSSpec *)&documentFSSpec,fsRdPerm);
  993.     
  994.     if (docResFile != -1)
  995.     {
  996.         // If there is still a temp size resource left over from a failed
  997.         // doc size change interaction.
  998.         // So, put the real SIZE resources back.
  999.         short numTempSizeRsrcs = 0;
  1000.         numTempSizeRsrcs = Count1Resources(kODTempSizeRsrcType);
  1001.         if( numTempSizeRsrcs > 0 )
  1002.         {
  1003.             // reopen with read-write permissions.
  1004.             CloseResFile( docResFile );
  1005.             docResFile = FSpOpenResFile((const FSSpec *)&documentFSSpec,fsRdWrPerm);
  1006.             err =  ReplaceResourceWithNewType( kODTempSizeRsrcType, kSIZERsrcType, 0 );
  1007.             err =  ReplaceResourceWithNewType( kODTempSizeRsrcType, kSIZERsrcType, 1 );
  1008.             // Now reopen with read-only permissions.
  1009.             CloseResFile( docResFile );
  1010.             docResFile = FSpOpenResFile((const FSSpec *)&documentFSSpec,fsRdPerm);
  1011.         }
  1012.  
  1013.         size0 = kODNULL;
  1014.         size0 = Get1Resource(kSIZERsrcType, 0);
  1015.         if (size0)
  1016.             DetachResource(size0);
  1017.         size1 = kODNULL;
  1018.         size1 = Get1Resource(kSIZERsrcType, 1);
  1019.         if (size1)
  1020.             DetachResource(size1);
  1021.         CloseResFile(docResFile);
  1022.         
  1023.         short stubResFile = FSpOpenResFile((const FSSpec *)&newFileSpec,fsRdWrPerm);
  1024.         if (size0)
  1025.             err = TestAndUpdate(size0,kSIZERsrcType,0);
  1026.         if (!err && size1)
  1027.             err = TestAndUpdate(size1,kSIZERsrcType,1);
  1028.         CloseResFile( stubResFile );
  1029.         
  1030.         if (size0)
  1031.             DisposeHandle(size0);
  1032.         if (size1)
  1033.             DisposeHandle(size1);
  1034.  
  1035.         UseResFile(theCurResFile);
  1036.     }
  1037.  
  1038.     return err;
  1039. }
  1040.  
  1041. //==============================================================================
  1042. // WasLaunchedThenActivate
  1043. //==============================================================================
  1044.  
  1045.  
  1046. ODBoolean    WasLaunchedThenActivate(
  1047.                         FSSpec* fileSpec,
  1048.                         DescType eventID,
  1049.                         OSErr & err)
  1050. {
  1051.     // check if the file we want to open is already open by someone on this machine
  1052.     ODULong        refNumCount = 0;
  1053.     RefNumPtr    refNums = kODNULL;
  1054.  
  1055.     CHECKR(GetLocalPaths(fileSpec, kDataFork, &refNumCount, &refNums), kODFalse);
  1056.     DisposePtr((Ptr) refNums);
  1057.     refNums = kODNULL;
  1058.     ODBoolean refnumForResFork = refNumCount == 0;    // don't count on
  1059.                                                     // refnumForResFork in the
  1060.                                                     // case where
  1061.                                                     // we're returning false
  1062.     if ( refnumForResFork )        // try again with the resource fork
  1063.     {
  1064.         CHECKR(GetLocalPaths(fileSpec, kResourceFork, &refNumCount, &refNums),
  1065.                 kODFalse);
  1066.         DisposePtr((Ptr) refNums);
  1067.         if (refNumCount == 0)
  1068.             return kODFalse;
  1069.     }
  1070.         
  1071.     AppleEvent    activateEvent, reply;
  1072.     AEDesc        addressDesc = {typeNull, kODNULL};
  1073.     ProcessSerialNumber psn = {0,kNoProcess};
  1074.     ProcessInfoRec aProcess;
  1075.     
  1076. //    DisposePtr((Ptr) refNums);        // <eeh> why doesn't this come before the return above?
  1077.     // create the activate event
  1078.     CHECKR(AECreateAppleEvent(kAEOpenDocSuite, kODActivateEvent, &addressDesc, 
  1079.                 kAutoGenerateReturnID, kAnyTransactionID, &activateEvent)
  1080.             , kODTrue);
  1081.  
  1082.     err = AEPutParamPtr(&activateEvent, keyDirectObject, typeFSS, 
  1083.                                         (Ptr) fileSpec, sizeof(*fileSpec));
  1084.     if (err != noErr)
  1085.     {
  1086.         AEDisposeDesc(&activateEvent);
  1087.         return kODTrue;
  1088.     }
  1089.  
  1090.     err = AEPutParamPtr(&activateEvent, keyODActivateEventCause, typeType, 
  1091.                                         (Ptr)&eventID, sizeof(eventID));
  1092.     if (err != noErr)
  1093.     {
  1094.         AEDisposeDesc(&activateEvent);
  1095.         return kODTrue;
  1096.     }
  1097.     
  1098.     if ( refnumForResFork )
  1099.     {
  1100.         err = AEPutParamPtr( &activateEvent, keyODRefnumFromResource,
  1101.                 typeBoolean, (Ptr)&refnumForResFork,
  1102.                 sizeof(refnumForResFork) );
  1103.         if (err != noErr)
  1104.         {
  1105.             AEDisposeDesc(&activateEvent);
  1106.             return kODTrue;
  1107.         }
  1108.     }
  1109.  
  1110.     // send the activate event to all OpenDoc processes
  1111.     aProcess.processInfoLength = sizeof(ProcessInfoRec);
  1112.     aProcess.processName = kODNULL;
  1113.     aProcess.processAppSpec = kODNULL;
  1114.     
  1115.     while (GetNextProcess(&psn) == noErr)
  1116.         if (GetProcessInformation(&psn, &aProcess) == noErr)
  1117.             if (aProcess.processType != 'APPL' &&
  1118.                 aProcess.processSignature == kODShellSignature)
  1119.             {
  1120.                 CHECKR(
  1121.                     AECreateDesc(typeProcessSerialNumber, (Ptr) &psn, sizeof(psn),
  1122.                                  &addressDesc)
  1123.                     , kODTrue);
  1124.  
  1125.                 CHECKR(AEPutAttributeDesc(&activateEvent, keyAddressAttr, &addressDesc)
  1126.                         , kODTrue);
  1127.                 CHECKR(AESend(&activateEvent, &reply, kAENoReply, kAENormalPriority,
  1128.                                 kAEDefaultTimeout, kODNULL, kODNULL)
  1129.                         , kODTrue);
  1130.                 // this shouldn't error since the handler always returns noErr
  1131.                 // ASSERT that reply == {typeNull, 0}
  1132.  
  1133.                 InitCursor();
  1134.  
  1135.                 CHECKR(AEDisposeDesc(&addressDesc), kODTrue);
  1136.             }
  1137.     err = AEDisposeDesc(&activateEvent);
  1138.     return kODTrue;
  1139. }
  1140.  
  1141. //------------------------------------------------------------------------------
  1142. // VerifyAndLaunchDocumentStub
  1143. //------------------------------------------------------------------------------
  1144.  
  1145. OSErr VerifyAndLaunchDocumentStub(AEDesc *theDocument, AEDescList* otherParams,
  1146.         ProcessSerialNumber *psn, DescType eventID, FSSpec* seedFSSPtr, 
  1147.         ODBoolean unsavedDoc)
  1148. {
  1149.     // if the document isn't local or can't be written to, make a local stub
  1150.     // in temp items folder.
  1151.     
  1152.     FSSpec documentStub;
  1153.     FSSpec documentSpec;
  1154.     DocStubType isDuplicate;
  1155.     OSErr err;
  1156.  
  1157.     err = MakeDocumentStub(theDocument, &documentStub, &documentSpec,
  1158.                             &isDuplicate, eventID, unsavedDoc);
  1159.     if (isDuplicate == kIsAlreadyLaunched)
  1160.         return err;
  1161.         
  1162.     if (!err)
  1163.     {
  1164.         if (unsavedDoc) {
  1165.             // If this doesn't work, will be tried again the next time doc is
  1166.             //    launched.
  1167.             err = VerifyDocumentStub(&documentSpec, kODNULL);
  1168.         }
  1169.         err = VerifyDocumentStub(&documentStub, seedFSSPtr);
  1170.         if (!err && documentStub.name[0]!=0) {
  1171.             // need to get the alias here rather than coerce in LaunchDocument,
  1172.             // as the AEM can't coerce FSS->Alias, at least when AOCE docs are
  1173.             // involved.
  1174.             // $Opt: Remove alias stuff if unnecessary for non AOCE docs.
  1175.             AEDesc theAlias;
  1176.             OSErr aliasErr = 1;            // so won't pass test below unless set
  1177.             if (isDuplicate == kIsSameAsStub)
  1178.                 aliasErr = NewAliasMinimal(&documentStub,
  1179.                         (AliasHandle *)&theAlias.dataHandle);
  1180.     
  1181.             if (seedFSSPtr == kODNULL ||
  1182.                 seedFSSPtr->vRefNum != documentStub.vRefNum ||
  1183.                 seedFSSPtr->parID != documentStub.parID ||
  1184.                 seedFSSPtr->name[0] != documentStub.name[0])
  1185.             {
  1186.                 if (!aliasErr) {
  1187.                     theAlias.descriptorType = typeAlias;
  1188.                     err= LaunchDocumentStub(theDocument, &documentStub, &theAlias,
  1189.                         otherParams, psn, eventID);
  1190.                     AEDisposeDesc(&theAlias);
  1191.                 } else
  1192.                     err= LaunchDocumentStub(theDocument, &documentStub, kODNULL,
  1193.                         otherParams, psn, eventID);
  1194.             }
  1195.         }
  1196.     }
  1197.     return err;
  1198. }
  1199.  
  1200. //------------------------------------------------------------------------------
  1201. // GetPrefsFileSpec
  1202. //------------------------------------------------------------------------------
  1203.  
  1204. OSErr GetPrefsFileSpec(ODFileSpec* prefFileSpec)
  1205. {
  1206.     CInfoPBRec        pb;
  1207.     memset (&pb,0,sizeof(pb));
  1208.  
  1209.     FindFolder(kOnSystemDisk, kPreferencesFolderType, kCreateFolder, 
  1210.                             &pb.dirInfo.ioVRefNum, &pb.dirInfo.ioDrDirID);
  1211.     StringHandle prefsFileName = GetString( kSHLPrefsFileNameResID );
  1212.  
  1213.     if ( !prefsFileName )
  1214.         ODPrcsDebugStr( "couldn't find kSHLPrefsFileNameResID str resource" );
  1215.  
  1216.     StringHandle prefsFolderName = GetString( kSHLPrefsFolderNameResID );
  1217.  
  1218.     if ( !prefsFolderName )
  1219.         ODPrcsDebugStr( "couldn't find kSHLPrefsFolderNameResID str resource" );
  1220.  
  1221.     //ODGetString(prefFolderName,kODPrefsFolderNameStrID);
  1222.  
  1223.     Str63 name; //must be an array because sizeof depends on it below
  1224.     //CopyPascalString(name,*prefsFolderName);
  1225.     BlockMove(*prefsFolderName,name,sizeof(name));    
  1226.     
  1227.     pb.dirInfo.ioNamePtr = name;
  1228.     pb.dirInfo.ioFDirIndex = 0;
  1229.     OSErr result = PBGetCatInfoSync( &pb );
  1230.     if (result == noErr)
  1231.     {
  1232.         if( pb.hFileInfo.ioFlFndrInfo.fdFlags & kIsAlias ) {
  1233.             FSSpec spec;
  1234.             ODBoolean targetIsFolder, wasAliased;
  1235.             FSMakeFSSpec(pb.dirInfo.ioVRefNum,pb.dirInfo.ioDrParID,name, &spec);
  1236.             result =  ResolveAliasFile(&spec, kODTrue, &targetIsFolder, &wasAliased);
  1237.             if (result == noErr)
  1238.             {
  1239.                 if( !targetIsFolder )
  1240.                     result = dirNFErr;
  1241.                 // Now get dir ID of target folder:
  1242.                 pb.dirInfo.ioNamePtr = spec.name;
  1243.                 pb.dirInfo.ioFDirIndex = 0;
  1244.                 pb.dirInfo.ioVRefNum = spec.vRefNum;
  1245.                 pb.dirInfo.ioDrDirID = spec.parID;
  1246.                 result = PBGetCatInfoSync( &pb );
  1247.             }
  1248.         }
  1249.     
  1250.         if (result == noErr)
  1251.         {
  1252.             FSMakeFSSpec(pb.dirInfo.ioVRefNum, pb.dirInfo.ioDrDirID, *prefsFileName, prefFileSpec);
  1253.             ReleaseResource( (Handle)prefsFileName );
  1254.             ReleaseResource( (Handle)prefsFolderName );
  1255.         }
  1256.     }
  1257.     return result;
  1258. }
  1259.  
  1260. //------------------------------------------------------------------------------
  1261. // GetPrefSizeResource
  1262. //------------------------------------------------------------------------------
  1263.  
  1264. static ODHandle GetPrefSizeResource()
  1265. {
  1266.     ODHandle prefSize = kODNULL;
  1267.     short theCurResFile = CurResFile();
  1268.     // Code partially copied from Prefs.cpp, should probably call a common util function
  1269.     ODFileSpec        prefFileSpec;
  1270.     OSErr result = GetPrefsFileSpec(&prefFileSpec);
  1271.     if (result == noErr)
  1272.     {
  1273.         ODSShort         prefResFile;
  1274.         prefResFile = FSpOpenResFile((const FSSpec *)&prefFileSpec,fsRdPerm);
  1275.         
  1276.         if (prefResFile != -1)
  1277.         {
  1278.             prefSize = Get1Resource(kSIZERsrcType, kSIZEID);
  1279.             if (prefSize)
  1280.                 DetachResource(prefSize);
  1281.             CloseResFile( prefResFile );
  1282.             UseResFile(theCurResFile);
  1283.         }
  1284.     }
  1285.     return prefSize;
  1286. }
  1287.  
  1288. //------------------------------------------------------------------------------
  1289. // TestAndUpdate
  1290. //------------------------------------------------------------------------------
  1291.  
  1292. // Check the doc's resource against the original copy.
  1293. static OSErr TestAndUpdate(Handle origRsrc,ResType rtype,short rid)
  1294. {
  1295.     // For SIZE-1, we need to check to see if there is an override in OpenDoc Prefs
  1296.     OSErr result = noErr;
  1297.     ODHandle prefSize = kODNULL;
  1298.     if (rtype == kSIZERsrcType && rid == kSIZEID)
  1299.     {
  1300.         prefSize = GetPrefSizeResource();
  1301.         if (prefSize != kODNULL)
  1302.             origRsrc = prefSize;
  1303.     }
  1304.     
  1305.     Handle docRsrc = Get1Resource(rtype, rid);
  1306.     
  1307.     do {            // just to have something to break out of...
  1308.         if (docRsrc) 
  1309.         {
  1310.             // Doc has resource. Compare data and possibly update:
  1311.             Size origSize = GetHandleSize(origRsrc);
  1312.             if (GetHandleSize(docRsrc)!=origSize
  1313.                                 || ODXmemcmp(*origRsrc,*docRsrc,origSize)!=0) 
  1314.             {
  1315.                 SetHandleSize(docRsrc, origSize);            // Rsrc contents are different
  1316.                 if ( (result = MemError()) != noErr )
  1317.                     break;
  1318.                 BlockMove(*origRsrc,*docRsrc,origSize);        // so copy over the original data
  1319.                 ChangedResource(docRsrc);
  1320.                 result = ResError();                        // Something bad happened...
  1321.                 break;
  1322.             }
  1323.             else
  1324.                 break;
  1325.         } 
  1326.         else 
  1327.         {
  1328.             result = ResError();
  1329.             if (result!=noErr && result!=resNotFound)
  1330.                 break;
  1331.             
  1332.             // No such rsrc in document, so add one:
  1333.             docRsrc = origRsrc;
  1334.             if ( (result = HandToHand(&docRsrc)) != noErr )
  1335.                 break;
  1336.             AddResource(docRsrc,rtype,rid,nil);
  1337.             result = ResError();
  1338.         }
  1339.     } while ( false );
  1340.     if (prefSize != kODNULL)
  1341.         DisposeHandle(prefSize);
  1342.     return result;
  1343. }
  1344.  
  1345.  
  1346. //==============================================================================
  1347. // VerifyDocument
  1348. //==============================================================================
  1349.  
  1350. OSErr VerifyDocumentStub(FSSpec *theStub, FSSpec* seedFSSPtr)
  1351. {
  1352. // VerifyDocumentStub precondition: theStub is writable or it is an OpenDoc Editor
  1353. // All resources are verified on both 68K & PPC.
  1354. // if the FSSpec passed in is an OpenDoc Editor
  1355. // then we create a stationery pad seed file and
  1356. //  munge the FSSpec to point to it instead
  1357.  
  1358.     // First, grab my original copies of the rsrcs to be stuffed into the document:
  1359.     Handle origRsrc[kNumDocStubRsrcs] = { kODNULL, kODNULL, kODNULL, kODNULL };
  1360.         
  1361.     OSErr err = noErr;
  1362.     ODUShort i = 0;
  1363.     do {
  1364.         origRsrc[i] = GetResource(docStubRsrcType[i],docStubRsrcID[i]);
  1365.     } while (origRsrc[i] != kODNULL && ++i<kNumDocStubRsrcs);
  1366.         
  1367.     if (i != kNumDocStubRsrcs)
  1368.         return ResError() ? ResError() :resNotFound;        // Some resource is missing
  1369.  
  1370.     // If we are opening a shared library, create a stationery seed file:
  1371.     FInfo finderInfo;
  1372.     FSpGetFInfo(theStub,&finderInfo);
  1373.     if (finderInfo.fdType == kCFragLibraryFileType ||
  1374.         finderInfo.fdType == kODSpecialEditorType)
  1375.     {
  1376.         CHECK(CreateStationerySeed(theStub, seedFSSPtr));
  1377.     } 
  1378.     else if (finderInfo.fdType == kPrefFileType) 
  1379.     {
  1380.         theStub->name[0] = 0;
  1381.         Str255    errorString;
  1382.         GetIndString(errorString, kODXLibsFldrStrID,
  1383.                         kODXTriedToOpenPrefsStrIndex);
  1384.         ReportErrorGeneric(errorString);
  1385. #if 0
  1386.         Str255 s;
  1387.         GetIndString(s, kODXLibsFldrStrID, 2); // EASTER EGG!
  1388.         if (s[0])
  1389.         {
  1390.             ParamText(s,"\p","\p","\p");
  1391.             NoteAlert(2001,NULL);
  1392.         }
  1393. #endif /* 0 */
  1394.         return noErr;
  1395.     }
  1396.     else if (finderInfo.fdType == 'APPL')
  1397.     {
  1398.         theStub->name[0] = 0;
  1399.     }
  1400.     
  1401.  
  1402.     if (theStub->name[0] == 0)  // File was non-Editor shared library, or unable to create stub
  1403.         return noErr;
  1404.         
  1405.     // Now open (or create) the document's resource fork:
  1406.     short theCurResFile = CurResFile();
  1407.     short docRefNum = FSpOpenResFile(theStub,fsRdWrPerm);
  1408.     if ((err = ResError()) != noErr)
  1409.     {
  1410.         // Need to create resource fork if there is none:
  1411.         if (err == eofErr)
  1412.         {
  1413.             // If other than eofErr, something's wrong
  1414.             // would have expected fnfErr. 
  1415.             // if the create fails, we might try settting the eof to 0.
  1416.             // and trying the create again
  1417.             FSpCreateResFile(theStub,finderInfo.fdCreator,finderInfo.fdType,smSystemScript);
  1418.             if ((err = ResError()) == noErr)
  1419.             {
  1420.                 docRefNum = FSpOpenResFile(theStub,fsRdWrPerm);
  1421.                 err = ResError();
  1422.             }
  1423.         }
  1424.         if (err != noErr)
  1425.             return err;
  1426.     }
  1427.  
  1428.     // Finally, verify, add, and/or update the document resources:
  1429.     for (i = 0; i<kNumDocStubRsrcs && err==noErr; ++i)
  1430.     {
  1431.         err = TestAndUpdate(origRsrc[i],copiedRsrcType[i],copiedRsrcID[i]);
  1432.     }
  1433.     
  1434.     // Clean up our toys and go home:
  1435.     CloseResFile(docRefNum);
  1436.     if (!err)
  1437.         err= ResError();
  1438.         
  1439.     UseResFile(theCurResFile);
  1440.     
  1441.     return err;
  1442. }
  1443.  
  1444.  
  1445. //==============================================================================
  1446. // CreateStationerySeed
  1447. //==============================================================================
  1448.  
  1449. static OSErr CreateStationerySeed(FSSpec *theDocument, FSSpec* seedFSSPtr)
  1450. {
  1451.     // note that coming in, theDocument is actually the Editor library;
  1452.     // going out, theDocument is the newly created Stationery Seed
  1453.     // seedFSSPtr is used if already set (name[0]≠0), else it is filled in.
  1454.     // IF seedFSSPtr is NOT filled in, then theDocument name is set to null.
  1455.  
  1456.     OSErr err = noErr;
  1457.     ODEditor   editorID = kODNULL;
  1458.     EditorUserStringList*    editorUsrStrgPairs = kODNULL;
  1459.     ODUShort editorCount = 0;
  1460.     EditorUserStringList* pair = kODNULL;
  1461.     
  1462. // First, read in the editorUserString NMAP from the Editor library
  1463.     short saveResFile = CurResFile();
  1464.     short resRefNum = FSpOpenResFile(theDocument,fsRdPerm);
  1465.     if ((err = ResError()) != noErr)
  1466.         return err;
  1467.     
  1468.     err = GetEditorUserStringPairs(resRefNum, &editorUsrStrgPairs, &editorCount);
  1469.     CloseResFile(resRefNum);
  1470.     UseResFile(saveResFile);
  1471.     if (err != noErr)
  1472.         return err;
  1473.  
  1474.     if (editorCount == 0)
  1475.     {
  1476.         theDocument->name[0] = 0;
  1477.         return noErr;
  1478.     }
  1479.     
  1480. // Loop through the list of editor/editorUserString pairs 
  1481. //    (libraries may contain more than one editor)
  1482.  
  1483.     for (pair = editorUsrStrgPairs;
  1484.             pair;
  1485.             pair = pair->next)
  1486.     {
  1487.         long length = pair->editor[0];
  1488.         Handle editor = NewHandleClear(1+length);
  1489.         if (MemError())
  1490.             return MemError();
  1491.         HLock(editor);
  1492.         BlockMove((Ptr)&pair->editor[1], (Ptr)*editor, length);
  1493.         HUnlock(editor);
  1494.         Str255 editorName;
  1495.         editorName[0] = pair->name.theText[0];
  1496.         BlockMove((Ptr)&pair->name.theText[1], (Ptr)&editorName[1], editorName[0]);
  1497.  
  1498.         if (seedFSSPtr != kODNULL && seedFSSPtr->name[0] != 0)
  1499.         {
  1500.             *theDocument = *seedFSSPtr;
  1501.         }
  1502.         else
  1503.         {
  1504.             // Create the stationery seed.  Note: this file is NOT user visible!
  1505.             // I.e. Don't have a cow about the hard coded string.
  1506.             CreateUniqueTmpFolderForFile(theDocument, "\pStationery Seed");
  1507.             FSpCreateResFile(theDocument,kODShellSignature,kODShellSignature,smSystemScript);
  1508.             CHECK(ResError());
  1509.             if (seedFSSPtr != kODNULL)
  1510.                 *seedFSSPtr = *theDocument;
  1511.         }
  1512.         
  1513.     // Plant the 'seed' resource
  1514.         saveResFile = CurResFile();
  1515.         ODSShort    seedRefNum;
  1516.         seedRefNum = FSpOpenResFile(theDocument,fsRdWrPerm);
  1517.         CHECK(ResError());
  1518.         
  1519.         AddResource(editor, kDocSeedResType, Unique1ID(kDocSeedResType), editorName);
  1520.         err= ResError();
  1521.         CloseResFile(resRefNum);
  1522.         UseResFile(saveResFile);
  1523.     }
  1524.  
  1525.     for (pair = editorUsrStrgPairs;
  1526.         pair;)
  1527.     {
  1528.         EditorUserStringList* nextPair = pair->next;
  1529.         DisposePtr( (Ptr)pair );
  1530.         pair = nextPair;
  1531.     }
  1532.     return err;
  1533. }
  1534.  
  1535. //==============================================================================
  1536. // string stuff
  1537. //==============================================================================
  1538.  
  1539. static char ODXmemcmp(char* buffer1,char* buffer2,unsigned int len)
  1540. {
  1541.   while (len-- > 0)
  1542.       if (*buffer1++ != *buffer2++)
  1543.           return (*--buffer1)-(*--buffer2);
  1544.   return 0;
  1545. }
  1546.  
  1547. static size_t    ODXstrlen(const char *s)
  1548. {
  1549.     size_t len = 0;
  1550.     while (*s++) ++len;
  1551.     return len;
  1552. }
  1553.  
  1554. static char*     ODXstrncpy(char* destStr, char* srcStr, size_t n)
  1555. {
  1556.     char* ret = destStr;
  1557.     while (n-- > 0)
  1558.         if ((*destStr++ = *srcStr++) == 0)
  1559.         {
  1560.             while (n-- > 0)
  1561.                 *destStr++ = '\0';
  1562.                 
  1563.             break;
  1564.         }
  1565.         
  1566.     return ret;    
  1567. }
  1568.  
  1569. static char*     ODXstrncat(char* destStr, char* srcStr, size_t n)
  1570. {
  1571.     size_t len = ODXstrlen(destStr);
  1572.     destStr += len;
  1573.     return ODXstrncpy(destStr, srcStr, n);
  1574. }
  1575.  
  1576.  
  1577. //==============================================================================
  1578. // Launching the document process
  1579. //==============================================================================
  1580.  
  1581. //==============================================================================
  1582. // LaunchDocumentStub
  1583. //==============================================================================
  1584.  
  1585. OSErr LaunchDocumentStub(AEDesc* theDocument, FSSpec *documentStub,
  1586.         AEDesc* theAlias, AEDescList* otherParams, ProcessSerialNumber *psn,
  1587.         DescType eventID)
  1588. {
  1589.     
  1590.     ODUnused(otherParams);
  1591.     
  1592.     LaunchParamBlockRec    launchPB;
  1593.     OSErr                err;
  1594.  
  1595.     launchPB.launchBlockID = extendedBlock;
  1596.     launchPB.launchEPBLength = extendedBlockLen;
  1597.     launchPB.launchControlFlags = launchContinue | launchNoFileFlags;
  1598.     launchPB.launchAppSpec = documentStub;
  1599.  
  1600.     AEDesc launchDesc = {typeNull, NULL};
  1601.     AEDescList theList = {typeNull, NULL};
  1602.     AppleEvent theEvent = {typeNull, NULL};
  1603.     AEDesc myAddress;
  1604.     myAddress.descriptorType = nil;
  1605.     myAddress.dataHandle = nil;
  1606.     
  1607.     CHECK(AECreateAppleEvent(kCoreEventClass, eventID, &myAddress,
  1608.                         kAutoGenerateReturnID, kAnyTransactionID, &theEvent));
  1609. //    if (otherParams)
  1610. //        CHECK(AEPutParamDesc(&theEvent, kKeySpecialParams, otherParams));
  1611.  
  1612.     CHECK(AECreateList(nil,0,false,&theList));
  1613.     if (theAlias)
  1614.         CHECK(AEPutDesc(&theList, 0, theAlias));
  1615.     else
  1616.         CHECK(AEPutDesc(&theList, 0, theDocument));
  1617.     CHECK(AEPutParamDesc(&theEvent, keyDirectObject, &theList));
  1618.  
  1619.     CHECK(AECoerceDesc(&theEvent, typeAppParameters, &launchDesc));
  1620. /*
  1621.     This may look a little weird, since we're actually moving the event out of the
  1622.     AppParameters descriptor.  But it's necessary, the coercison to typeAppParameters
  1623.     takes the 'aevt' and puts it all in one handle, instead of
  1624.     leaving it as a AEDesc.  So, only one handle is being added to
  1625.     the launch parameter block instead of an AEDesc.
  1626. */
  1627.     HLock(launchDesc.dataHandle);
  1628.     launchPB.launchAppParameters = (AppParametersPtr)*(launchDesc.dataHandle);
  1629.  
  1630. #if defined(powerc) || defined(__powerc)
  1631. #else
  1632.     FlushInstructionCache();
  1633.     FlushDataCache();
  1634. #endif
  1635.  
  1636.     err= LaunchApplication(&launchPB);
  1637.     
  1638.     if (psn)
  1639.         *psn = launchPB.launchProcessSN;
  1640.     
  1641.     AEDisposeDesc( &launchDesc );
  1642.     AEDisposeDesc( &theList );
  1643.     AEDisposeDesc( &theEvent );
  1644.     
  1645.     return err;
  1646. }
  1647.  
  1648.  
  1649. ODBoolean myEqualPascalStrings(ConstStr255Param str1, ConstStr255Param str2)
  1650. {
  1651.     if (str1[0] != str2[0])
  1652.         return kODFalse;
  1653.     for (int i = 1; i <= str1[0]; i++)
  1654.     {
  1655.         if (str1[i] != str2[i])
  1656.             return kODFalse;
  1657.     }
  1658.     return kODTrue;
  1659. }
  1660.  
  1661.  
  1662. /*
  1663. **    Apple Macintosh Developer Technical Support
  1664. **
  1665. **    File:    GetLocalPaths.c
  1666. **
  1667. **    by Jim Luther, Apple Developer Technical Support
  1668. **
  1669. **    Copyright © 1995 Apple Computer, Inc.
  1670. **    All rights reserved.
  1671. */
  1672.  
  1673.  
  1674. pascal    OSErr    GetLocalPaths(FSSpec *spec,
  1675.                               ForkType fork,
  1676.                               unsigned long *refNumCount,
  1677.                               RefNumPtr *refNums)
  1678. {
  1679.     enum
  1680.     {
  1681.         kMaxFCBs = 348    /* The maximum number of local access paths under System 7 */
  1682.     };
  1683.     
  1684.     OSErr        result;
  1685.     FCBPBRec    pb;
  1686.     short        index;
  1687.     Str31        tempName;
  1688.     RefNumPtr    tempRefNums;
  1689.     
  1690.     /* initialize returned values */
  1691.     *refNumCount = 0;
  1692.     *refNums = NULL;
  1693.     
  1694.     /* Allocate temp storage for refNum matches */
  1695.     tempRefNums = (RefNumPtr)NewPtr(kMaxFCBs * sizeof(short));
  1696.     
  1697.     if ( tempRefNums != NULL )
  1698.     {
  1699.         /* Get FCB name in tempName */
  1700.         pb.ioNamePtr = tempName;
  1701.         
  1702.         /* Index through the open paths on the volume specified by spec->vRefNum */
  1703.         pb.ioVRefNum = spec->vRefNum;
  1704.         index = 1;
  1705.         do
  1706.         {
  1707.             pb.ioRefNum = 0;
  1708.             pb.ioFCBIndx = index;
  1709.             result = PBGetFCBInfoSync(&pb);
  1710.             if ( result == noErr )
  1711.             {
  1712.                 /*
  1713.                 **    See if parent directory ID matches and
  1714.                 **    file name matches and
  1715.                 **    the file fork (resource or data) matches
  1716.                 */
  1717.                 if ( (pb.ioFCBParID == spec->parID) &&
  1718.                      EqualString(spec->name, tempName, false, true) &&
  1719.                      ((fork == kResourceFork) == ((pb.ioFCBFlags & (1 << 9)) != 0)) )
  1720.                 {
  1721.                     /* It's a match - add it to the array of matches */
  1722.                     tempRefNums[*refNumCount] = pb.ioRefNum;
  1723.                     ++(*refNumCount);
  1724.                 }
  1725.                 ++index;    /* next FCB index */
  1726.             }
  1727.         } while ( result == noErr );
  1728.         
  1729.         /* These errors are OK - they mean we hit the end of the FCB list */
  1730.         if ( (result == rfNumErr) || (result == fnOpnErr) )
  1731.         {
  1732.             result = noErr;
  1733.         }
  1734.         
  1735.         if ( (result == noErr) && (*refNumCount != 0) )
  1736.         {
  1737.             /* Allocate memory to return refNum matches in */
  1738.             *refNums = (RefNumPtr)NewPtr(*refNumCount * sizeof(short));
  1739.             if ( *refNums != NULL )
  1740.             {
  1741.                 /* Move refNums from tempRefNums to *refNums */
  1742.                 BlockMoveData((Ptr)tempRefNums, (Ptr)*refNums, (*refNumCount * sizeof(short)));
  1743.             }
  1744.             else
  1745.             {
  1746.                 /* Couldn't allocate memory for refNum array */
  1747.                 result = memFullErr;
  1748.             }
  1749.         }
  1750.         
  1751.         /* Free up tempRefNums storage */ 
  1752.         DisposePtr((Ptr)tempRefNums);
  1753.     }
  1754.     else
  1755.     {
  1756.         /* Couldn't allocate temp memory */
  1757.         result = memFullErr;
  1758.     }
  1759.     
  1760.     return ( result );
  1761. }
  1762.  
  1763. //------------------------------------------------------------------------------
  1764. // GetEditorUserStringPairs
  1765. //------------------------------------------------------------------------------
  1766.  
  1767. OSErr GetEditorUserStringPairs(ODSShort resRefNum, 
  1768.                             EditorUserStringList** pairs, ODUShort* editorCount)
  1769. {
  1770.     Handle         theEdtrUSnmap = kODNULL;
  1771.     *editorCount = 0;
  1772.     ODError result = noErr;
  1773.     
  1774.     if( resRefNum != -1 ) {
  1775.         ODSShort nmapCount = Count1Resources( kODNameMappings );
  1776.         if ((result = ResError()) != noErr)
  1777.             return result;
  1778.             
  1779.         for (short i=1; i<=nmapCount; i++) 
  1780.         {
  1781.                 // Get the Resource
  1782.             ODHandle nmap = (ODHandle)Get1IndResource(kODNameMappings, i);
  1783.             if ((result = ResError()) != noErr)
  1784.                 return result;
  1785.             
  1786.             if ( nmap != nil && !result  )
  1787.             {
  1788.                 HLock((ODHandle) nmap);
  1789.  
  1790.                 result = GetEditorSetFromNMAP(nmap, pairs, editorCount);
  1791.                                          
  1792.                 ReleaseResource( nmap );
  1793.             }
  1794.             
  1795.             if ((*editorCount > 0) || (result != 0))
  1796.                 break;
  1797.         }
  1798.     }
  1799.     return result;
  1800. }
  1801.  
  1802. //------------------------------------------------------------------------------
  1803. // GetEditorSetFromNMAP
  1804. //------------------------------------------------------------------------------
  1805.  
  1806. OSErr GetEditorSetFromNMAP( ODHandle nmap, EditorUserStringList** pairs, 
  1807.                                                          ODUShort* editorCount )
  1808. {
  1809.     ODISOStr        nameSpaceName = kODNULL; ODVolatile(nameSpaceName);
  1810.     ODUShort        nameLen;
  1811.     ODUShort        editorLen;
  1812.     ODSize            bufferPos=(ODSize)*nmap;
  1813.     ODSize            sizeShort = sizeof(ODUShort);
  1814.     OSErr            result = noErr;
  1815.     
  1816.     BlockMove((ODPtr)bufferPos, (ODPtr)&nameLen, sizeShort);
  1817.     bufferPos += sizeShort;
  1818.  
  1819.     nameSpaceName = (ODISOStr)NewPtrClear((ODSize)nameLen+1);
  1820.     if (!nameSpaceName)
  1821.         result = memFullErr;
  1822.     else
  1823.     {
  1824.         BlockMove((ODPtr)bufferPos, (ODPtr)nameSpaceName, (ODSize)nameLen);
  1825.         bufferPos += (ODSize)nameLen;
  1826.         
  1827.         if (!ODXmemcmp(nameSpaceName,kODEditorUserString,ODXstrlen(kODEditorUserString)))
  1828.         {
  1829.             BlockMove((ODPtr)bufferPos,(ODPtr)editorCount, sizeShort);
  1830.             bufferPos += sizeShort;
  1831.             
  1832.             if ( *editorCount > 0 )
  1833.             {
  1834.     
  1835.                 *pairs = (EditorUserStringList*)NewPtrClear(
  1836.                                               sizeof(EditorUserStringList));
  1837.                 if (!*pairs)
  1838.                     result = memFullErr;
  1839.                 else
  1840.                 {
  1841.                     EditorUserStringList* thisPair = *pairs;
  1842.                     
  1843.                     for(ODUShort i=0; i < *editorCount && thisPair; i++)
  1844.                     {
  1845.                         BlockMove((ODPtr)bufferPos,(ODPtr)&editorLen,sizeShort);
  1846.                         bufferPos += sizeShort;
  1847.                         
  1848.                         thisPair->editor[0] = editorLen;
  1849.                         BlockMove((ODPtr)bufferPos,(ODPtr)&thisPair->editor[1],
  1850.                                                          (ODSize)editorLen);
  1851.                         bufferPos += (ODSize)editorLen;
  1852.                         bufferPos += sizeShort;
  1853.                                         
  1854.                             // read UserString from the nmap
  1855.                         BlockMove((ODPtr)bufferPos, 
  1856.                             (ODPtr)&thisPair->name.theScriptCode,sizeof(ScriptCode));
  1857.                         bufferPos += sizeof(ScriptCode);
  1858.                         BlockMove((ODPtr)bufferPos, 
  1859.                             (ODPtr)&thisPair->name.theLangCode,sizeof(LangCode));
  1860.                         bufferPos += sizeof(LangCode);
  1861.                         BlockMove((ODPtr)bufferPos,(ODPtr)&nameLen,sizeShort);
  1862.                         bufferPos += sizeShort;
  1863.                         thisPair->name.theText[0] = nameLen;
  1864.                         BlockMove((ODPtr)bufferPos,(ODPtr)&thisPair->name.theText[1], nameLen);
  1865.                         bufferPos += nameLen;
  1866.                         
  1867.                         if (i+1 < *editorCount )
  1868.                         {
  1869.                             thisPair->next = (EditorUserStringList*)NewPtrClear(
  1870.                                               sizeof(EditorUserStringList));
  1871.                             thisPair = thisPair->next;
  1872.                             if (!thisPair)
  1873.                                 result = memFullErr;
  1874.  
  1875.                         }
  1876.                     }
  1877.                 }
  1878.             }
  1879.         }
  1880.     }
  1881.  
  1882.     DisposePtr(nameSpaceName);
  1883.     return result;
  1884. }
  1885.  
  1886. //------------------------------------------------------------------------------
  1887. // MoveToTrash -- $$$$$ duplicated from Prefs.cpp
  1888. //------------------------------------------------------------------------------
  1889. static void
  1890. MoveToTrash( short vRefnum, long dirID, Str255 name )
  1891. {
  1892.     short foundVRefNum;
  1893.     long  foundDirID;
  1894.     
  1895.     if(!FindFolder(vRefnum, kTrashFolderType, kDontCreateFolder, 
  1896.                                 &foundVRefNum, &foundDirID))
  1897.     {
  1898.  
  1899.         CMovePBRec paramBlock ;
  1900.         memset( ¶mBlock, 0, sizeof(paramBlock) );
  1901.         
  1902.         paramBlock.ioNamePtr = name ;
  1903.         paramBlock.ioVRefNum = foundVRefNum ;
  1904.         paramBlock.ioNewDirID = foundDirID ;
  1905.         paramBlock.ioDirID = dirID ;
  1906.         
  1907.         (void) HDelete(foundVRefNum,foundDirID,name);     // ignore error (may not exist)
  1908.         OSErr result = PBCatMoveSync( ¶mBlock );
  1909.         if (result)
  1910.             (void) HDelete(vRefnum,dirID,name); 
  1911.     }
  1912.     else
  1913.         (void) HDelete(vRefnum,dirID,name); 
  1914. }
  1915.  
  1916.  
  1917. //------------------------------------------------------------------------------
  1918. // IsSystem753OrGreater
  1919. //------------------------------------------------------------------------------
  1920.  
  1921. ODBoolean IsSystem753OrGreater()
  1922. {
  1923.     return IsCertainSystemVersionOrGreater(0x753);
  1924. }
  1925.  
  1926. //------------------------------------------------------------------------------
  1927. // IsSystem8OrGreater
  1928. //------------------------------------------------------------------------------
  1929.  
  1930. ODBoolean IsSystem8OrGreater()
  1931. {
  1932.     return IsCertainSystemVersionOrGreater(0x800);
  1933. }
  1934.  
  1935. //------------------------------------------------------------------------------
  1936. // IsCertainSystemVersionOrGreater
  1937. //------------------------------------------------------------------------------
  1938.  
  1939. ODBoolean IsCertainSystemVersionOrGreater(long systemVersion)
  1940. {
  1941.     long    response;
  1942.  
  1943.     OSErr error = Gestalt(gestaltSystemVersion, &response);
  1944.     return LoWord(response) >= systemVersion;
  1945.     if (error)
  1946.         ODPrcsDebugStr("IsCertainSystemVersionOrGreater: Unexpected error from Gestalt!");
  1947. }
  1948.  
  1949. //------------------------------------------------------------------------------
  1950. //    ChangeDesktopDatabase
  1951. //
  1952. //    Add/remove an app of creator kODShellSignature to/from desktop database
  1953. //    If there is a problem, it fails silently (What other recourse?)
  1954. //------------------------------------------------------------------------------
  1955.  
  1956. void ChangeDesktopDatabase(FSSpec* fileSpec, ODBoolean add)
  1957. {
  1958.     DTPBRec    pb;
  1959.     OSErr    err;
  1960.  
  1961.     // CHECK FOR AVAILABILITY OF DESKTOP MANAGER
  1962.     {
  1963.         HParamBlockRec            volParams;
  1964.         GetVolParmsInfoBuffer    info;
  1965.     
  1966.         memset(&volParams, 0, sizeof(volParams));
  1967.  
  1968.         volParams.ioParam.ioVRefNum = fileSpec->vRefNum;
  1969.         volParams.ioParam.ioBuffer = (Ptr)&info;
  1970.         volParams.ioParam.ioReqCount = sizeof(info);
  1971.  
  1972.         err = PBHGetVolParmsSync(&volParams);
  1973.         if (err || volParams.ioParam.ioReqCount != volParams.ioParam.ioActCount)
  1974.         {
  1975.             ODPrcsDebugStr("ChangeDesktopDatabase: Error calling PBHGetVolParmsSync");
  1976.             return;
  1977.         }
  1978.  
  1979.         if ( ! (info.vMAttrib & 1<<bHasDesktopMgr))
  1980.         {
  1981.             ODPrcsDebugStr("ChangeDesktopDatabase: Hey man, no desktop database available?");
  1982.             return;
  1983.         }
  1984.     }
  1985.  
  1986.     memset(&pb, 0, sizeof(pb));
  1987.  
  1988.     pb.ioNamePtr = NULL;
  1989.     pb.ioVRefNum = fileSpec->vRefNum;
  1990.     err = PBDTGetPath(&pb);
  1991.     if (err)
  1992.     {
  1993.         ODPrcsDebugStr("ChangeDesktopDatabase: Error getting reference to desktop DB");
  1994.         return;
  1995.     }
  1996.  
  1997.     pb.ioNamePtr = fileSpec->name;
  1998.     pb.ioNamePtr = fileSpec->name;
  1999.     pb.ioDirID = fileSpec->parID;
  2000.     pb.ioFileCreator = kODShellSignature;
  2001.     
  2002.     if (add)
  2003.     {
  2004.         err = PBDTAddAPPLSync(&pb);
  2005.         if (err)
  2006.         {
  2007.             ODPrcsDebugStr("ChangeDesktopDatabase: Error adding APPL");
  2008.             return;
  2009.         }
  2010.     }
  2011.     else
  2012.     {
  2013.         // DON'T CARE AT ALL ABOUT ERRORS HERE.
  2014.         err = PBDTRemoveAPPLSync(&pb);
  2015.         if (err)
  2016.             return;
  2017.     }
  2018.  
  2019.     (void) PBDTFlushSync(&pb);
  2020. }
  2021. #if 0 /* LAUNCHER CAN'T USE EXCEPTION HANDLING. I SHOULD ADD THIS IN THOUGH. */
  2022. //------------------------------------------------------------------------------
  2023. //    EnableApp
  2024. //------------------------------------------------------------------------------
  2025.  
  2026. void EnableApp(FSSpec* fileSpec)
  2027. {
  2028.     TRY
  2029.         TempPlatformFile    file = new PlatformFile;
  2030.         
  2031.         file->Specify(fileSpec);
  2032.         
  2033.         file->SetPlatformCreator(kODShellSignature);
  2034.         ChangeDesktopDatabase(fileSpec, kODAppAPPL);
  2035.     CATCH_ALL
  2036.     ENDTRY
  2037. }
  2038.  
  2039. //------------------------------------------------------------------------------
  2040. //    DisableApp
  2041. //------------------------------------------------------------------------------
  2042.  
  2043. void EnableApp(FSSpec* fileSpec)
  2044. {
  2045.     TRY
  2046.         TempPlatformFile    file = new PlatformFile;
  2047.         
  2048.         file->Specify(fileSpec);
  2049.         
  2050.         file->SetPlatformCreator(kODShellSignature);
  2051.         ChangeDesktopDatabase(fileSpec, kODAppAPPL);
  2052.     CATCH_ALL
  2053.     ENDTRY
  2054. }
  2055. #endif
  2056. //------------------------------------------------------------------------------
  2057. // GetOpenDocLibsFolderInfo
  2058. //
  2059. //    Return directory ID of the OpenDoc Libraries folder. This ID can be used
  2060. //    to find items INSIDE this folder. It is NOT the ID of the folder's parent.
  2061. //------------------------------------------------------------------------------
  2062.  
  2063. OSErr GetOpenDocLibsFolderInfo(long* dirID, short* vRefNum)
  2064. {
  2065.     long        libsFldrDirID;
  2066.     short        libsFldrVRefNum;
  2067.     Str255        folderName;
  2068.     OSErr        result = noErr;
  2069.  
  2070.     GetIndString(folderName, kODXLibsFldrStrID, kODXLibsFldrStrIndex);
  2071.  
  2072.     if (folderName[0] == 0)
  2073.         ODPrcsDebugStr("Resource Error: OpenDoc Libraries string not found!");
  2074.     
  2075.     result = FindFolder(kOnSystemDisk, kExtensionFolderType, 
  2076.                                 kDontCreateFolder, &libsFldrVRefNum, 
  2077.                                 &libsFldrDirID);
  2078.             
  2079.     if (result == noErr)
  2080.     {
  2081.         CInfoPBRec        CinfoPB;
  2082.  
  2083.         memset (&CinfoPB, 0 ,sizeof(CinfoPB));
  2084.  
  2085.         CinfoPB.dirInfo.ioNamePtr = (StringPtr)&folderName;
  2086.         CinfoPB.dirInfo.ioFDirIndex = 0;
  2087.         CinfoPB.dirInfo.ioVRefNum = libsFldrVRefNum;
  2088.         CinfoPB.dirInfo.ioDrDirID = libsFldrDirID;
  2089.         
  2090.         result = PBGetCatInfoSync(&CinfoPB);
  2091.         if (result == noErr)
  2092.         {
  2093.             
  2094.  
  2095.             *dirID = CinfoPB.dirInfo.ioDrDirID;
  2096.             *vRefNum = libsFldrVRefNum;
  2097.         }
  2098.     }
  2099.     
  2100.     return result;
  2101. }
  2102.  
  2103. //------------------------------------------------------------------------------
  2104. // FindODLibFileWithSignature
  2105. //
  2106. //    Given the dirID and vRefNum of the OpenDoc Libraries folder, find a file
  2107. //    with a particular signature.
  2108. //
  2109. //    Result is returned in fileName.
  2110. //------------------------------------------------------------------------------
  2111.  
  2112. OSErr FindODLibFileWithSignature(Str255 fileName,
  2113.                                     short vRefNum,
  2114.                                     long dirID,
  2115.                                     OSType signature)
  2116. {
  2117.     OSErr        error;
  2118.     CInfoPBRec    catInfo;
  2119.  
  2120.     // LOOP THROUGH ALL THE FILES IN THE FOLDER
  2121.     memset (&catInfo, 0, sizeof(catInfo));
  2122.     catInfo.dirInfo.ioNamePtr = fileName;
  2123.     catInfo.dirInfo.ioFDirIndex = 1;
  2124.     catInfo.dirInfo.ioVRefNum = vRefNum;
  2125.     catInfo.dirInfo.ioDrDirID = dirID;
  2126.  
  2127.     for(error = PBGetCatInfoSync(&catInfo); 
  2128.                     error == noErr; 
  2129.                    error = PBGetCatInfoSync(&catInfo))
  2130.     {
  2131.         // if this is a folder
  2132.         if ((catInfo.dirInfo.ioFlAttrib & (1<<4))) 
  2133.         {
  2134.             // IGNORE IT
  2135.         }
  2136.         else
  2137.         {
  2138.             // if this is an alias
  2139.             if ((catInfo.hFileInfo.ioFlFndrInfo.fdFlags & 0x8000) /* kIsAlias */)
  2140.             {
  2141.                 // IGNORE IT
  2142.             }
  2143.             else
  2144.             {
  2145.                 FInfo    fileInfo;
  2146.                 FSSpec    fileSpec;
  2147.  
  2148.                 CopyPascalString(fileSpec.name, fileName);
  2149.                 fileSpec.parID = dirID;
  2150.                 fileSpec.vRefNum = vRefNum;
  2151.                 error = FSpGetFInfo(&fileSpec, &fileInfo);
  2152.                 if (!error && fileInfo.fdCreator == signature)
  2153.                 {
  2154.                     error = noErr;
  2155.                     break;
  2156.                 }
  2157.             }
  2158.         }
  2159.  
  2160.         catInfo.hFileInfo.ioFDirIndex++;
  2161.         //need to do this each time since PBGetCatInfo call returns val here
  2162.         catInfo.hFileInfo.ioNamePtr = fileName;
  2163.         catInfo.hFileInfo.ioVRefNum = vRefNum;
  2164.         catInfo.hFileInfo.ioDirID = dirID;  
  2165.     }
  2166.  
  2167.     return error;
  2168. }
  2169.  
  2170. //------------------------------------------------------------------------------
  2171. //    RunningUnderMacOS8
  2172. //------------------------------------------------------------------------------
  2173.  
  2174. ODBoolean RunningUnderMacOS8()
  2175. {
  2176.     Str255    errorString;
  2177.  
  2178.     if (IsSystem8OrGreater())
  2179.     {
  2180.         GetIndString(errorString, kSHLMiscErrorStringsStrID,
  2181.                                     kSHLCannotRunUnderMacOS8Index);
  2182.         ReportErrorGeneric(errorString);
  2183.         return kODTrue;
  2184.     }
  2185.     return kODFalse;
  2186. }
  2187.  
  2188. //==============================================================================
  2189. // NEW PREFS RESOURCE (odst) INTERFACE
  2190. //==============================================================================
  2191.  
  2192. // I WANTED TO PUT THESE IN THE HEADER FOR THE CLASS, BUT THE COMPILER
  2193. //    COMPLAINED.
  2194.  
  2195. const OSType        kSetupPrefsResourceType = 'odst';
  2196. const short            kSetupPrefsResourceID = 0;
  2197. const Boolean        kRunAtSysStartupDefault = 0;
  2198. const Boolean        kRunTilSysShutdownDefault = 0;
  2199. const long            kLatestVersion = 0;
  2200.  
  2201. //------------------------------------------------------------------------------
  2202. //    ODSetUpPrefs::ODSetUpPrefs
  2203. //------------------------------------------------------------------------------
  2204.  
  2205. ODSetUpPrefs::ODSetUpPrefs(short refNum, short permissions)
  2206. {
  2207.     if (refNum < 0)
  2208.     {
  2209.         fRefNum = OpenODPrefsResFile(true, fsRdWrPerm);
  2210.         if (fRefNum < 0)
  2211.         {
  2212.             fRefNum = OpenODPrefsResFile(true, fsRdPerm);
  2213.             fPermissions = fsRdPerm;
  2214.         }
  2215.         else
  2216.             fPermissions = fsRdWrPerm;
  2217.         fOpenedFileMyself = true;
  2218.     }
  2219.     else
  2220.     {
  2221.         fRefNum = refNum;
  2222.         fPermissions = permissions;
  2223.         fOpenedFileMyself = false;
  2224.     }
  2225.     
  2226.     fResource = (ODSetupPrefsResourceH)Get1Resource(kSetupPrefsResourceType,
  2227.                                                     kSetupPrefsResourceID);
  2228.     if (!fResource)
  2229.     {
  2230.         // USE DEFAULTS AND MAKE BRAND NEW RESOURCE
  2231.         fRunAtSysStartup = kRunAtSysStartupDefault;
  2232.         fRunTilSysShutdown = kRunTilSysShutdownDefault;
  2233.  
  2234.         fResource = (ODSetupPrefsResourceH)NewHandle(
  2235.                                                 sizeof(ODSetupPrefsResource));
  2236.         if (fResource)
  2237.         {
  2238.             (**fResource).runAtSysStartup = fRunAtSysStartup;
  2239.             (**fResource).runTilSysShutdown = fRunTilSysShutdown;
  2240.             (**fResource).version = kLatestVersion;
  2241.             AddResource((Handle)fResource, kSetupPrefsResourceType,
  2242.                         kSetupPrefsResourceID, "\p");
  2243.             WriteResource((Handle)fResource);
  2244.         }
  2245.     }
  2246.     else
  2247.     {
  2248.         // READ DATA FROM RESOURCE
  2249.         fRunAtSysStartup = (**fResource).runAtSysStartup;
  2250.         fRunTilSysShutdown = (**fResource).runTilSysShutdown;
  2251.     }
  2252. }
  2253.  
  2254. //------------------------------------------------------------------------------
  2255. //    ODSetUpPrefs::~ODSetUpPrefs
  2256. //------------------------------------------------------------------------------
  2257.  
  2258. ODSetUpPrefs::~ODSetUpPrefs()
  2259. {
  2260.     if (fOpenedFileMyself)
  2261.         CloseResFile(fRefNum);
  2262. }
  2263. #if 0
  2264. //------------------------------------------------------------------------------
  2265. //    ODSetUpPrefs::GetRunAtSysStartup
  2266. //------------------------------------------------------------------------------
  2267.  
  2268. Boolean    ODSetUpPrefs::GetRunAtSysStartup()
  2269. {
  2270.     return fRunAtSysStartup;
  2271. }
  2272. #endif /* 0 */
  2273. //------------------------------------------------------------------------------
  2274. //    ODSetUpPrefs::GetRunTilSysShutdown
  2275. //------------------------------------------------------------------------------
  2276.  
  2277. Boolean    ODSetUpPrefs::GetRunTilSysShutdown()
  2278. {
  2279.     return fRunTilSysShutdown;
  2280. }
  2281. #if 0
  2282. //------------------------------------------------------------------------------
  2283. //    ODSetUpPrefs::SetRunAtSysStartup
  2284. //------------------------------------------------------------------------------
  2285.  
  2286. OSErr ODSetUpPrefs::SetRunAtSysStartup(Boolean runAtSysStartup)
  2287. {
  2288.     OSErr    error;
  2289.  
  2290.     if (fPermissions == fsRdPerm)
  2291.         error = fLckdErr;
  2292.     else
  2293.     {
  2294.         (**fResource).runAtSysStartup = runAtSysStartup;
  2295.         error = this->UpdateFile();
  2296.         if (!error)
  2297.             fRunAtSysStartup = runAtSysStartup;
  2298.     }
  2299.     return error;
  2300. }
  2301. #endif /* 0 */
  2302. //------------------------------------------------------------------------------
  2303. //    ODSetUpPrefs::SetRunTilSysShutdown
  2304. //------------------------------------------------------------------------------
  2305.  
  2306. OSErr ODSetUpPrefs::SetRunTilSysShutdown(Boolean runTilSysShutdown)
  2307. {
  2308.     OSErr    error;
  2309.  
  2310.     if (fPermissions == fsRdPerm)
  2311.         error = fLckdErr;
  2312.     else
  2313.     {
  2314.         (**fResource).runTilSysShutdown = runTilSysShutdown;
  2315.         error = this->UpdateFile();
  2316.         if (!error)
  2317.             fRunTilSysShutdown = runTilSysShutdown;
  2318.     }
  2319.     return error;
  2320. }
  2321.  
  2322. //------------------------------------------------------------------------------
  2323. //    ODSetUpPrefs::UpdateFile
  2324. //------------------------------------------------------------------------------
  2325.  
  2326. OSErr ODSetUpPrefs::UpdateFile()
  2327. {
  2328.     OSErr    error;
  2329.  
  2330.     ChangedResource((Handle)fResource);
  2331.     error = ResError();
  2332.     if (!error)
  2333.     {
  2334.         WriteResource((Handle)fResource);
  2335.         error = ResError();
  2336.     }
  2337.     return error;
  2338. }
  2339.  
  2340. //------------------------------------------------------------------------------
  2341. //    ODSetUpPrefs::GetDefaultSize
  2342. //------------------------------------------------------------------------------
  2343.  
  2344. OSErr ODSetUpPrefs::GetDefaultSize(Size& size)
  2345. {
  2346.     return GetODDefaultSize(fRefNum, size);
  2347. }
  2348.  
  2349. //------------------------------------------------------------------------------
  2350. //    ODSetUpPrefs::SetDefaultSize
  2351. //------------------------------------------------------------------------------
  2352.  
  2353. OSErr ODSetUpPrefs::SetDefaultSize(Size newSize)
  2354. {
  2355.     return SetODDefaultSize(fRefNum, newSize);
  2356. }
  2357.  
  2358. //==============================================================================
  2359. // ReplaceSizeWithTemp
  2360. // Function to save a resource in another resource.
  2361. //==============================================================================
  2362.  
  2363. OSErr ReplaceResourceWithNewType( ResType typeToDelete, ResType typeToAdd, short id )
  2364. {
  2365. // dh - Boy, is there ever mucho foo going on here!
  2366. // The problem is that you can't just copy a resource. NOOOOO! That would be too easy!
  2367.  
  2368. // 1. First, we must detach the resource we are copying because there can't be two
  2369. // references to a handle by multiple resource entries.
  2370.  
  2371. // 2. Second problem is that if there is an existing resource of the same type and
  2372. // id that you want to write out, the new one will be written, but not overwrite
  2373. // the existing one. That means you will have an unusable resource that can never
  2374. // be accessed! So, we go through and remove any copies of that resource
  2375. // that may already be there.
  2376.  
  2377. // 3. Third, when we copy the resource, we must also copy the res attributes. But, we
  2378. // must make sure to set the changed flag so that it will actually get written to
  2379. // disk when updating, since obviously the original resource will NOT have this 
  2380. // attribute set.
  2381. // I must credit Scott Knaster for a number of these suggestions. He's been there!
  2382.  
  2383.     ODBoolean continuing = kODFalse;
  2384.     Handle tempHandle = kODNULL;
  2385.     Handle theOldSizeRsrc = kODNULL;
  2386.     Handle theTempSizeRsrc = kODNULL;
  2387.     Handle theoldTempSRsrc = kODNULL;
  2388.     OSErr  theErr = noErr;
  2389.     short origResAttrs =0;
  2390.  
  2391.     theTempSizeRsrc = Get1Resource(typeToDelete, id);
  2392.     origResAttrs = GetResAttrs(theTempSizeRsrc);
  2393.     
  2394.     if( theTempSizeRsrc && ResError() == noErr )
  2395.     {
  2396.         // This implements comment #1.
  2397. //        DetachResource(theTempSizeRsrc);
  2398.         tempHandle = theTempSizeRsrc;
  2399.         theErr = HandToHand( &tempHandle );
  2400.         
  2401.         // This implements comment #2.
  2402.         do
  2403.         {
  2404.             theoldTempSRsrc = GetResource( typeToAdd,id );
  2405.             if( theoldTempSRsrc )
  2406.             {
  2407.                 RemoveResource(theoldTempSRsrc);
  2408.                 theErr = ResError();
  2409.                 if( theErr  == noErr )
  2410.                 {
  2411.                     DisposeHandle( theoldTempSRsrc );
  2412.                     continuing = kODTrue;
  2413.                 }
  2414.             }
  2415.         }
  2416.         while( continuing == kODTrue);
  2417.  
  2418.         AddResource(tempHandle,typeToAdd,id,nil);
  2419.         theErr = ResError();
  2420.         if( theErr  == noErr )
  2421.         {
  2422.             // This implements comment #3.
  2423.             SetResAttrs(tempHandle, origResAttrs);
  2424.             ChangedResource( tempHandle );
  2425.             // Now, nuke the SIZE resource.
  2426.             theOldSizeRsrc = GetResource( typeToDelete,id );
  2427.             if( theOldSizeRsrc )
  2428.             {
  2429.                 RemoveResource(theOldSizeRsrc);
  2430.                 theErr = ResError();
  2431.                 DisposeHandle( theOldSizeRsrc );
  2432.             }
  2433.         }
  2434.     }
  2435.     
  2436.     ReleaseResource( tempHandle );
  2437.  
  2438.     return ResError();
  2439. }
  2440.  
  2441.